• iOS 通知扩展插件


    iOS 通知扩展插件

    • Notification Content Extension

      • 通知内容扩展,是在展示通知时展示一个自定义的用户界面。
    • Notification Service Extension

      • 通知服务扩展,是在收到通知后,展示通知前,做一些事情的。比如,增加附件,网络请求等。

    Notification Service Extension

    • 目前只找到aps推送支持
    • 主要是处理一下附件相关的下载

    新建一个target

    • 老的xcode版本开启VoIP功能也是在 Background Modes 中直接勾选就开启了,但是新版的xcode移除了这个选项,所以只能在 info.plist 文件中去手动添加
    • 参考1
    • 参考2

    代码实现

    @interface NotificationService : UNNotificationServiceExtension
    
    @end
    
    
    #import "NotificationService.h"
    #import <UIKit/UIKit.h>
    
    @interface NotificationService ()
    
    @property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
    @property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
    
    @end
    
    @implementation NotificationService
    // 系统接到通知后,有最多30秒在这里重写通知内容(在此方法可进行一些网络请求,如上报是否收到通知等操作)
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
         NSLog(@"%s",__FUNCTION__);
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
        
        // Modify the notification content here...
        NSLog(@"%@",request.content);
        // 添加附件
        //1. 下载
        NSURL *url = [NSURL URLWithString:@"https://tva1.sinaimg.cn/large/008i3skNgy1gtir9lwnj0j61x40gsabl02.jpg"];
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
        NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            if (!error) {
                //2. 保存数据
                NSString *path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES).firstObject
                                  stringByAppendingPathComponent:@"download/image.jpg"];
                UIImage *image = [UIImage imageWithData:data];
                NSError *err = nil;
                [UIImageJPEGRepresentation(image, 1) writeToFile:path options:NSAtomicWrite error:&err];
                //3. 添加附件
                UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"remote-atta1" URL:[NSURL fileURLWithPath:path] options:nil error:&err];
                if (attachment) {
                    self.bestAttemptContent.attachments = @[attachment];
                }
            }else{
                self.bestAttemptContent.title = @"标题";
                    self.bestAttemptContent.subtitle = @"子标题";
                    self.bestAttemptContent.body = @"body";
            }
            //4. 返回新的通知内容
            self.contentHandler(self.bestAttemptContent);
        }];
        [task resume];
    }
    // 处理过程超时,则收到的通知直接展示出来
    - (void)serviceExtensionTimeWillExpire {
        NSLog(@"%s",__FUNCTION__);
        self.contentHandler(self.bestAttemptContent);
    }
    
    @end
    

    注意事项

    • UNNotificationAttachment:attachment 支持
      • 音频 5M(kUTTypeWaveformAudio/kUTTypeMP3/kUTTypeMPEG4Audio/kUTTypeAudioInterchangeFileFormat)
      • 图片10M(kUTTypeJPEG/kUTTypeGIF/kUTTypePNG)
      • 视频50M(kUTTypeMPEG/kUTTypeMPEG2Video/kUTTypeMPEG4/kUTTypeAVIMovie)

    UINotificationConentExtension

    配置项目

    • 新建target,打开推送服务

    配置info.plist

    • 配置info.plist,和Notification Service Extension进行关联

    • 找到这个 UNNotificationExtensionCategory,写到Notification Service Extension中,可以配置多个,对应多个界面
       self.bestAttemptContent.categoryIdentifier = @"myNotificationCategory";// 和NotificationConentExtension关联
        self.contentHandler(self.bestAttemptContent);
    

    自定义UI

    • 如果我们想要隐藏系统默认的内容页面,也就是下面的那部分,头是隐藏不了的;只需要在Info.plist里添加字段UNNotificationExtensionDefaultContentHidden,bool类型并设置其值为YES;

    • 可以直接修改stroryboard

    • 添加Action,可以添加基本的事件

    
    #import "NotificationViewController.h"
    #import <UserNotifications/UserNotifications.h>
    #import <UserNotificationsUI/UserNotificationsUI.h>
    
    @interface NotificationViewController () <UNNotificationContentExtension,UIActionSheetDelegate>
    
    @property IBOutlet UILabel *label;
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @end
    
    @implementation NotificationViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"%s",__FUNCTION__);
         // 添加action
        UNNotificationAction * likeAction;              //喜欢
        UNNotificationAction * ingnoreAction;           //取消
        UNTextInputNotificationAction * inputAction;    //文本输入
        
        likeAction = [UNNotificationAction actionWithIdentifier:@"action_like" title:@"点赞"
    options:UNNotificationActionOptionForeground];
        inputAction = [UNTextInputNotificationAction actionWithIdentifier:@"action_input"title:@"评论"
    options:UNNotificationActionOptionForeground                                                 textInputButtonTitle:@"发送"textInputPlaceholder:@"说点什么"];
    ingnoreAction = [UNNotificationAction actionWithIdentifier:@"action_cancel"title:@"忽略" options:UNNotificationActionOptionDestructive];
        NSString *categoryWithIdentifier = @"myNotificationCategory";// 和info.plist中配置的id一样
        UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:categoryWithIdentifier actions:@[likeAction,inputAction,ingnoreAction] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];
        
        NSSet *sets = [NSSet setWithObjects:category,nil];
        [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:sets];
    }
    
    - (void)didReceiveNotification:(UNNotification *)notification {
        self.label.text = notification.request.content.body;
        NSLog(@"didReceiveNotification:%@",notification.request.content);
        for (UNNotificationAttachment * attachment in notification.request.content.attachments) {
            NSLog(@"url:%@",attachment.URL);
            // 显示图片
            if([attachment.URL startAccessingSecurityScopedResource]){
                NSData *data = [NSData dataWithContentsOfURL:attachment.URL];
                self.imageView.image = [UIImage imageWithData:data];
                [attachment.URL stopAccessingSecurityScopedResource];
            }
        
        }
    }
    
    - (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption))completion {
        NSLog(@"response:%@",response);
        if ([response.actionIdentifier isEqualToString:@"action_like"]) {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                completion(UNNotificationContentExtensionResponseOptionDismiss);
            });
        } else if ([response.actionIdentifier isEqualToString:@"action_input"]) {
            UNTextInputNotificationResponse *inputAction = (UNTextInputNotificationResponse*)response;
            NSLog(@"输入内容:%@",inputAction.userText);
            // TODO: 发送评论
            completion(UNNotificationContentExtensionResponseOptionDismiss);
        } else if ([response.actionIdentifier isEqualToString:@"action_cancel"]) {
            completion(UNNotificationContentExtensionResponseOptionDismiss);
        } else {
            completion(UNNotificationContentExtensionResponseOptionDismiss);
        }
        completion(UNNotificationContentExtensionResponseOptionDoNotDismiss);
    }
    @end
    
    
    • info.plist

    • aps 格式
    {
    "aps":
        {
            "alert":
            {
                "title":"iOS10远程推送标题",
                "subtitle" : "iOS10 远程推送副标题",
                "body":"这是在iOS10以上版本的推送内容,并且携带来一个图片附件"
            },
            "badge":1,
            "mutable-content":1,
            "media":"image",
            "image-url":"https://tva1.sinaimg.cn/large/008i3skNgy1gtmd6b4whhj60fq0g6tb502.jpg"
        }
    }
    
    
  • 相关阅读:
    关于图灵测试和中文屋Chinese room的理解
    内核IPv4路由选择子系统(简述)
    window和linux的nacos安装
    Kubernetes控制平面组件:Scheduler调度器
    Flink-APl
    springboot大学生课堂考勤管理系统的设计与实现
    【无标题】
    嵌入式网络接口之MAC芯片与PHY芯片
    Vue轮播图
    【ELK】日志系统&部署
  • 原文地址:https://www.cnblogs.com/songliquan/p/15953648.html