美文网首页iOS底层音视频开发iOS开发基础知识
iOS10远程推送自定义通知---消息包含图片视频处理(全)

iOS10远程推送自定义通知---消息包含图片视频处理(全)

作者: 点点_星光 | 来源:发表于2018-10-12 14:54 被阅读78次

    不说废话,直接正题
    这里做消息的自定义通知页面,我会把一些需要注意的都写出来。
    1.通知创建、注册以及授权。
    注意:(1)包含头文件

    #ifdef NSFoundationVersionNumber_iOS_9_x_Max
    //iOS10通知新框架
    #import <UserNotifications/UserNotifications.h>
    //iOS10 自定义通知界面
    #import <UserNotificationsUI/UserNotificationsUI.h>
    #endif
    

    (2).Link Binary With Libraries包含相应的framework包


    屏幕快照 2018-10-12 下午2.28.00.png

    下面是Appdelegate的部分代码,包含了通知的代理方法和通知互动页面的代理方法

        /* -------------自定义通知------------- */
        //申请授权
        //1.创建通知中心
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        //设置通知中心的代理(iOS10之后监听通知的接收时间和交互按钮的响应是通过代理来完成的)
        center.delegate = self;
        //2.通知中心设置分类
        [center setNotificationCategories:[NSSet setWithObjects:[self createCatrgory], nil]];
        //3.请求授权
        /**UNAuthorizationOption
         UNAuthorizationOptionBadge   = (1 << 0),红色圆圈
         UNAuthorizationOptionSound   = (1 << 1),声音
         UNAuthorizationOptionAlert   = (1 << 2),内容
         UNAuthorizationOptionCarPlay = (1 << 3),车载通知     */
        [center requestAuthorizationWithOptions:UNAuthorizationOptionAlert|UNAuthorizationOptionBadge|UNAuthorizationOptionSound completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (granted == YES) {
                NSLog(@"授权成功");
            }
        }];
    
    //当APP处于前台的时候接收到通知
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
        //此处省略十万行代码
    }
    
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {
        //收到推送的请求
        UNNotificationRequest *request = response.notification.request;
        //收到推送的内容
        UNNotificationContent *content = request.content;
        //收到用户的基本信息
        NSDictionary *userInfo = content.userInfo;
        //收到推送消息的角标
        NSNumber *badge = content.badge;
        //收到推送消息body
        NSString *body = content.body;
        //推送消息的声音
        UNNotificationSound *sound = content.sound;
        // 推送消息的副标题
        NSString *subtitle = content.subtitle;
        // 推送消息的标题
        NSString *title = content.title;
        if ([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
            NSLog(@"iOS10 收到远程通知:%@",userInfo);
            //此处省略一万行需求代码。。。。。。
            NSString *msaage = @"";
            if ([response.actionIdentifier isEqualToString:@"textInputAction"]) {
                msaage = ((UNTextInputNotificationResponse *)response).userText;
                NSLog(@"input:%@", content);
            } else if ([response.actionIdentifier isEqualToString:@"getItforeGround"]) {
                NSLog(@"收到");
                msaage = @"收到";
            } else if ([response.actionIdentifier isEqualToString:@"kownDestructive"]) {
                NSLog(@"我现在不方便,等下再回复你");
                msaage = @"我现在不方便,等下再回复你";
            }
            NSString *msgType = userInfo[@"type"];
            NSString *msgTo   = userInfo[@"id"];
            // 发送消息
            [self sendMessageWith:msaage msgType:msgType msgTo:msgTo];
        } else {
            // 判断为本地通知
            //此处省略一万行需求代码。。。。。。
            NSLog(@"iOS10 收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
        }
        completionHandler();
    }
    
    #pragma mark - 创建通知分类(交互按钮)
    - (UNNotificationCategory *)createCatrgory {
        //文本交互(iOS10之后支持对通知的文本交互)
        /**options
         UNNotificationActionOptionAuthenticationRequired  用于文本
         UNNotificationActionOptionForeground  前台模式,进入APP
         UNNotificationActionOptionDestructive  销毁模式,不进入APP     */
        UNTextInputNotificationAction *textInputAction = [UNTextInputNotificationAction actionWithIdentifier:@"textInputAction" title:@"点击输入回复消息" options:UNNotificationActionOptionAuthenticationRequired textInputButtonTitle:@"发送" textInputPlaceholder:@"还有多少话要说……"];
        //不打开应用按钮   快捷回复
        UNNotificationAction *action1 = [UNNotificationAction actionWithIdentifier:@"getItforeGround" title:@"收到" options:UNNotificationActionOptionDestructive];
        UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:@"kownDestructive" title:@"我现在不方便,等下再回复你" options:UNNotificationActionOptionDestructive];
        //创建分类
        /**
         Identifier:分类的标识符,通知可以添加不同类型的分类交互按钮
         actions:交互按钮
         intentIdentifiers:分类内部标识符  没什么用 一般为空就行
         options:通知的参数
         UNNotificationCategoryOptionCustomDismissAction:自定义交互按钮
         UNNotificationCategoryOptionAllowInCarPlay:车载交互
         */
        UNNotificationCategory *category = [UNNotificationCategory
                                            categoryWithIdentifier:@"myMessageNotificationCategory"
                                            actions:@[textInputAction,action1,action2]
                                            intentIdentifiers:@[]
                                            options:UNNotificationCategoryOptionCustomDismissAction];
        return category;
    }
    

    2.创建target Notification Content Extension,步骤如下如


    屏幕快照 2018-10-12 上午10.21.39.png 屏幕快照 2018-10-12 上午10.23.14.png

    创建UI……此处略
    然后就是通过didReceiveNotification对空间赋值
    注意:此处需要注意的是图片、视频或者音频文件获取的时候一定要开启文件安全访问权限[attachment.URL startAccessingSecurityScopedResource],我因为没开启这个一直没权限打开,差点人给奔溃了:一直没有权限打开,还有当时不知道怎么打断点调试。

    - (void)didReceiveNotification:(UNNotification *)notification {
        if (notification.request.content.attachments.count > 0) {
            NSDictionary *userInfo = notification.request.content.userInfo;
            NSString *fileType = userInfo[@"media"][@"type"];
            UNNotificationAttachment *attachment = (UNNotificationAttachment *)notification.request.content.attachments.firstObject;
    //        self.label.text = [NSString stringWithFormat:@"%@", attachment.URL];
            if ([fileType isEqualToString:@"image"]) {
                //如果动态加载图片可以通过UNNotificationAttachment获取
                self.playerImageView.hidden = YES;
                if ([attachment.URL startAccessingSecurityScopedResource]) {//获取文件安全访问权限
                    NSData *imageData = [NSData dataWithContentsOfURL:attachment.URL];
                    UIImage *image = [UIImage imageWithData:imageData];
                    if (image.size.width <= self.view.frame.size.width - 20) {
                        _imgConstraintW.constant = image.size.width;
                        _imgConstraintH.constant = image.size.height;
                    } else {
                        _imgConstraintW.constant = self.view.frame.size.width - 20;
                        _imgConstraintH.constant = (self.view.frame.size.width - 20) * image.size.height/image.size.width;
                    }
                    [self.imgView setImage:image];
                    [attachment.URL stopAccessingSecurityScopedResource];//结束文件安全访问
                }
            } else if ([fileType isEqualToString:@"video"]) {
                if ([attachment.URL startAccessingSecurityScopedResource]) {
                    _playerImageViewH.constant = 40;
                    _playerImageView.image = [UIImage imageNamed:@"theme1_discover_icon_videoplaybig"];
                    NSURL *url = attachment.URL;
                    UIImage *image = [self firstFrameWithVideoURL:url size:CGSizeMake(self.view.frame.size.width, self.view.frame.size.width/2)];
                    if (image.size.width <= self.view.frame.size.width - 20) {
                        _imgConstraintW.constant = image.size.width;
                        _imgConstraintH.constant = image.size.height;
                    } else {
                        _imgConstraintW.constant = self.view.frame.size.width - 20;
                        _imgConstraintH.constant = (self.view.frame.size.width - 20) * image.size.height/image.size.width;
                    }
                    [self.imgView setImage:image];
    //                _imgConstraintH.constant = self.view.frame.size.width/2;
                    AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:url];
                    self.myPlayer = [[AVPlayer alloc] initWithPlayerItem:item];
                    self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.myPlayer];
                    self.playerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, image.size.height+20);
                    self.playerLayer.backgroundColor = [UIColor grayColor].CGColor;
                    //设置播放窗口和当前视图之间的比例显示内容
                    self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
                    [self.view.layer addSublayer:self.playerLayer];
                    self.myPlayer.volume = 1.0f;
                    [self.myPlayer play];
                    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.myPlayer.currentItem];
                    
                    [attachment.URL stopAccessingSecurityScopedResource];
                }
            }
        } else {
            _imgConstraintH.constant = 0;
            _playerImageView.hidden = YES;
        }
    }
    
    - (void)playbackFinished:(NSNotification *)notifi {
        NSLog(@"播放完成");
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
        self.myPlayer = nil;
        [self.playerLayer removeFromSuperlayer];
        self.playerLayer = nil;
    }
    
    #pragma mark ---- 获取图片第一帧
    - (UIImage *)firstFrameWithVideoURL:(NSURL *)url size:(CGSize)size
    {
        // 获取视频第一帧
        NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
        AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:opts];
        AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset];
        generator.appliesPreferredTrackTransform = YES;
        generator.maximumSize = CGSizeMake(size.width, size.height);
        NSError *error = nil;
        CGImageRef img = [generator copyCGImageAtTime:CMTimeMake(0, 10) actualTime:NULL error:&error];
    //    self.label.text = [NSString stringWithFormat:@"**%@  **%@", url, error];
        if (img) {
            return [UIImage imageWithCGImage:img];
        }
        return nil;
    }
    

    如果只有文字,以上就可以结束了。最后需要注意的是UNNotificationExtensionCategory要和你创建通知的时候id一致,同时也要和APS中的id一致。
    UNNotificationExtensionDefaultContentHidden这个是是否显示系统给的的通知页面


    屏幕快照 2018-10-12 上午10.16.08.png

    3.推送了图片、视频、音频文件需要打开的接着往下。由于这些都涉及到下载文件,所以我们需要一个创建target Notification Service Extension来拦截推送下载文件,创建如图


    屏幕快照 2018-10-12 上午10.25.23.png

    下面就是拦截后下载文件并打包的代码:

    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
        
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
        
        // 下载并关联附件
        NSString *urlString = self.bestAttemptContent.userInfo[@"media"][@"url"];
        
    //    #warning 这里是添加视频播放按钮
    //    NSString *fileType = self.bestAttemptContent.userInfo[@"media"][@"type"];
    //    if ([fileType isEqualToString:@"video"]) {
    //        
    //    }
        
        [self loadAttachmentForUrlString:urlString
                       completionHandler: ^(UNNotificationAttachment *attachment) {
                           self.bestAttemptContent.attachments = [NSArray arrayWithObjects:attachment, nil];
                           [self contentComplete];
                       }];
    }
    
    - (void)serviceExtensionTimeWillExpire {
        //这里进行操作超时后的补救···例如将图片替换成默认图片等等
        self.bestAttemptContent.title = @"下载资源超时";
        [self contentComplete];
    }
    
    - (void)contentComplete {
        [self.session invalidateAndCancel];
        self.contentHandler(self.bestAttemptContent);
    }
    
    - (void)loadAttachmentForUrlString:(NSString *)urlString
                     completionHandler:(void (^)(UNNotificationAttachment *))completionHandler {
        __block UNNotificationAttachment *attachment = nil;
        __block NSURL *attachmentURL = [NSURL URLWithString:urlString];
        NSString *fileExt = [@"." stringByAppendingString:[urlString pathExtension]];
        
        //下载附件
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
        NSURLSessionDownloadTask *task;
        task = [_session downloadTaskWithURL:attachmentURL
                           completionHandler: ^(NSURL *temporaryFileLocation, NSURLResponse *response, NSError *error) {
                               
                               if (error != nil) {
                                   NSLog(@"%@", error.localizedDescription);
                               } else {
                                   NSFileManager *fileManager = [NSFileManager defaultManager];
                                   NSURL *localURL = [NSURL fileURLWithPath:[temporaryFileLocation.path
                                                                             stringByAppendingString:fileExt]];
                                   NSLog(@"*****localURL:%@", localURL);
                                   [fileManager moveItemAtURL:temporaryFileLocation
                                                        toURL:localURL
                                                        error:&error];
                                   NSError *attachmentError = nil;
                                   NSString * uuidString = [[NSUUID UUID] UUIDString];
                                   //将附件信息进行打包
                                   attachment = [UNNotificationAttachment
                                                 attachmentWithIdentifier:uuidString
                                                 URL:localURL
                                                 options:nil
                                                 error:&attachmentError];
                                   if (attachmentError) {
                                       NSLog(@"%@", attachmentError.localizedDescription);
                                   }
                               }
                               
                               completionHandler(attachment);
                           }];
        [task resume];
    }
    

    最后贴上aps

    文字aps
    {
        "aps":{
            "alert":{
                "body":"test: 我不知道你在想什么,还是那个地点那条街",
                "title":"外滩十八号"
            },
            "badge":1,
            "category":"myMessageNotificationCategory",
            "sound":"default"
        },
        "id":"test",
        "type":"chat"
    }
    图片aps
    {
        "aps":{
            "alert":{
                "body":"test: 图片",
                "title":"外滩十八号"
            },
            "badge":1,
            "category":"myMessageNotificationCategory",
            "sound":"default",
            "mutable-content":"1"
        },
        "id":"test18",
        "type":"chat",
        "media":{
            "type":"image",
            "url":"https://www.fotor.com/images2/features/photo_effects/e_bw.jpg"
            }
    }
    视频aps
    {
        "aps":{
            "alert":{
                "body":"test: 视频",
                "title":"外滩十八号"
            },
            "badge":1,
        "category":"myMessageNotificationCategory",
            "sound":"default",
            "mutable-content":"1"
        },
        "id":"test18",
        "type":"chat",
        "media":{
            "type":"video",
            "url":"http://olxnvuztq.bkt.clouddn.com/WeChatSight1.mp4"
            }
    }
    

    4.在Notification Content Extension中获取文件,然后进行相应处理,步骤2代码中有图片和视频的一些处理。
    搞定收工。
    自定义通知调试参考
    https://github.com/liuyanhongwl/ios_common/blob/master/files/App-Extension-Tips.md
    推送工具下载
    https://github.com/KnuffApp/Knuff/releases

    因为在公司的app上做的,所以就没有demo,来两张效果图

    IMG_1173.PNG IMG_1172.PNG

    相关文章

      网友评论

        本文标题:iOS10远程推送自定义通知---消息包含图片视频处理(全)

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