美文网首页iOS
iOS推送 10 Notification Service Ex

iOS推送 10 Notification Service Ex

作者: 文子飞_ | 来源:发表于2021-07-10 15:58 被阅读0次

    我的项目是基于极光推送的
    证书都是配置好的 自动配置即可Automatically manage signing
    推送模拟都是自己在极光官网后台管理中模拟推送
    新需求就是推送栏有图片 长按可以查看图片

    推送效果

    image image

    推送原理(面试被问到这个问题很尴尬)

    苹果的推送服务通知是由自己专门的推送服务器APNs (Apple Push Notification service)来完成的,其过程是 APNs 接收到我们自己的应用服务器发出的被推送的消息,将这条消息推送到指定的 iOS 的设备上,然后再由 iOS设备通知到我们的应用程序,我们将会以通知或者声音的形式收到推送回来的消息。
    iOS 远程推送的前提是,装有我们应用程序的 iOS 设备,需要向 APNs 服务器注册,注册成功后,APNs 服务器将会给我们返回一个 devicetoken,我们获取到这个 token 后会将这个 token 发送给我们自己的应用服务器。当我们需要推送消息时,我们的应用服务器将消息按照指定的格式进行打包,然后结合 iOS 设备的 devicetoken 一起发给 APNs 服务器。我们的应用会和 APNs 服务器维持一个基于 TCP 的长连接,APNs 服务器将新消息推送到iOS 设备上,然后在设备屏幕上显示出推送的消息。

    Service Extension介绍

    image

    iOS 10之前,iOS推送只能实现文字消息。
    iOS10之后,苹果官方新增了一些特性,其中包括新的推送方式----推送拦截(Service Extension),这种推送方式允许iOS开发者对接收到的推送消息进行一定的处理,以便达到自己想要的效果。

    创建Extension

    • target

      image
    • Notification Service Extension

      image
    • 启动这个计划

      image
    • 效果图

      image
    image
    • 在info.plist文件中添加http协议防止图片视频资源加载不了

      image

    模拟推送

    iOS 10 新增的 Notification Service Extension 功能,用 mutable-content 字段来控制。
    若使用 Web 控制台,需勾选 “可选设置”中 mutable-content 选项;若使用 RESTFul API 需设置 mutable-content 字段为 true。

    未勾选mutable-content

    image image

    控制台打印 (手动点击通知栏 打印的推送通知)

    {
        image = https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg9.doubanio.com%2Fview%2Fgroup_topic%2Fl%2Fpublic%2Fp244659466.jpg&refer=http%3A%2F%2Fimg9.doubanio.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1617951781&t=583f7008a65ffdbc66e99bf797d1cbbb;
        _j_business = 1;
        _j_uid = 53107055958;
        name = wpp;
        _j_msgid = 58547001073413082;
        aps = {
        alert = {
        title = 测试Extension;
        body = iOS10新特性;
    }
    ;
        badge = 1;
        sound = default;
    }
    ;
    }
    
    

    勾选mutable-content

    image image

    发现和之前未勾选mutable-content有所区别就是标题后面多[modified] -> 说明通知已经被拦截

    控制台参数

    {
        name = wpp;
        _j_business = 1;
        _j_uid = 53107055958;
        _j_msgid = 67554201063374418;
        image = https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg9.doubanio.com%2Fview%2Fgroup_topic%2Fl%2Fpublic%2Fp244659466.jpg&refer=http%3A%2F%2Fimg9.doubanio.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1617951781&t=583f7008a65ffdbc66e99bf797d1cbbb;
        aps = {
        mutable-content = 1;
        alert = {
        title = 测试Extension;
        body = iOS10新特性;
    }
    ;
        badge = 1;
        sound = default;
    }
    ;
    }
    
    

    其实就是aps多一个参数 mutable-content = 1;
    查看代码 发现创建的NotificationService.m中 有主动创建拦截处理通知

    image
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
    
        // Modify the notification content here...
        self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title];
    
        self.contentHandler(self.bestAttemptContent);
    }
    
    

    处理拦截

    切换运行target

    image image

    代码

    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *contentToDeliver))contentHandler;
    - (void)serviceExtensionTimeWillExpire;
    
    

    第一个方法是用于拦截通知并处理好通知
    第二个方法是当方法一资源超时则会调用默认这里走原始推送即可

    推送设置

    type:image、video
    url:连接
    //https://fcvideo.cdn.bcebos.com/smart/f103c4fc97d2b2e63b15d2d5999d6477.mp4
    
    //https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg9.doubanio.com%2Fview%2Fgroup_topic%2Fl%2Fpublic%2Fp244659466.jpg&refer=http%3A%2F%2Fimg9.doubanio.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1617951781&t=583f7008a65ffdbc66e99bf797d1cbbb
    
    

    编写代码并测试效果

    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
        self.bestAttemptContent.title = [NSString stringWithFormat:@"%@", self.bestAttemptContent.title];
        [self handleRequest:request];
    }
    - (void)handleRequest:(UNNotificationRequest *)request
    {
        if ([request.content.userInfo.allKeys containsObject:@"url"] && [request.content.userInfo.allKeys containsObject:@"type"]) {
            NSString *url = request.content.userInfo[@"url"];
            NSString *type = request.content.userInfo[@"type"];
            NSString *fileExt = [self fileExtensionForMediaType:type];
            //UNNotificationAttachment
            NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
            [[session downloadTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                if (error) {
                    NSLog(@"%@",error.localizedDescription);
                } else {
                    NSFileManager *fileManager = [NSFileManager defaultManager];
                    NSURL *localURL = [NSURL fileURLWithPath:[location.path stringByAppendingString:fileExt]];
                    [fileManager moveItemAtURL:location toURL:localURL error:&error];
                    NSError *attachmentError = nil;
                    UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" URL:localURL options:nil error:&attachmentError];
                    if (attachmentError) {
                        NSLog(@"报错:%@", attachmentError.localizedDescription);
                    } else {
                        self.bestAttemptContent.attachments = @[attachment];
                        self.contentHandler(self.bestAttemptContent);
                    }
                }
            }]resume];
        } else {
            self.contentHandler(self.bestAttemptContent);
        }
    }
    - (void)serviceExtensionTimeWillExpire
    {
        self.contentHandler(self.bestAttemptContent);
    }
    #pragma mark - utils
    - (NSString *)fileExtensionForMediaType:(NSString *)type {
        NSString *ext = type;
        if ([type isEqualToString:@"image"]) {
            ext = @"jpg";
        }
        if ([type isEqualToString:@"video"]) {
            ext = @"mp4";
        }
        if ([type isEqualToString:@"audio"]) {
            ext = @"mp3";
        }
        return [@"." stringByAppendingString:ext];
    }
    
    

    图片截图就不要了 如上面截图 下面截图是视频截图

    image image

    UNNotificationAction

    /*
     UNNotificationActionOptionAuthenticationRequired  执行前需要解锁确认
     UNNotificationActionOptionDestructive  显示高亮(红色)
     UNNotificationActionOptionForeground  将会引起程序启动到前台
     */
    NSMutableArray *actionMutableArr = [[NSMutableArray alloc] initWithCapacity:1];
    UNNotificationAction * actionA = [UNNotificationAction actionWithIdentifier:@"ActionA" title:@"不感兴趣" options:UNNotificationActionOptionAuthenticationRequired];
    UNNotificationAction * actionB = [UNNotificationAction actionWithIdentifier:@"ActionB" title:@"不感兴趣" options:UNNotificationActionOptionDestructive];
    UNNotificationAction * actionC = [UNNotificationAction actionWithIdentifier:@"ActionC" title:@"进去瞅瞅" options:UNNotificationActionOptionForeground];
    UNTextInputNotificationAction * actionD = [UNTextInputNotificationAction actionWithIdentifier:@"ActionD" title:@"作出评论" options:UNNotificationActionOptionDestructive textInputButtonTitle:@"send" textInputPlaceholder:@"say some thing"];
    
    [actionMutableArr addObjectsFromArray:@[actionA,actionB,actionC,actionD]];
    
    if (actionMutableArr.count)
    {
        UNNotificationCategory * notficationCategory = [UNNotificationCategory categoryWithIdentifier:@"categoryNoOperationAction" actions:actionMutableArr intentIdentifiers:@[@"ActionA",@"ActionB",@"ActionC",@"ActionD"] options:UNNotificationCategoryOptionCustomDismissAction];
        [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObject:notficationCategory]];
    }
    
    
    image

    自定义UI contentExtension(长按查看通知界面)

    image image image

    UNNotificationExtensionDefaultContentHidden 为YES 隐藏系统UI

    然后设置在NotificationService.m中设置categoryIdentifier

    self.bestAttemptContent.categoryIdentifier = @"myNotificationCategory";
    
    

    上架报错?

    提示要配置证书 展示配置把
    配置证书这边

    image

    先配置Identifiers

    image

    配置Profiles

    image

    点击安装profiles 证书不需要 就之前原工厂证书即可

    image

    打包

    image

    作者:守护地中海的花
    链接:https://www.jianshu.com/p/966da14e68e3
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    相关文章

      网友评论

        本文标题:iOS推送 10 Notification Service Ex

        本文链接:https://www.haomeiwen.com/subject/euvcpltx.html