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"
}
}

iOS 通知扩展插件的更多相关文章

  1. 使用 Swift 制作一个新闻通知中心插件(1)

    input[type="date"].form-control,.input-group-sm>input[type="date"].input-grou ...

  2. Swift 制作一个新闻通知中心插件1

    使用 Swift 制作一个新闻通知中心插件(1) 随着 iOS 8 的发布,苹果为开发者们开放了很多新的 API,而在这些开放的接口中 通知中心插件 无疑是最显眼的一个.通知中心就不用过多介绍了,相信 ...

  3. 使用 Swift 制作一个新闻通知中心插件(2)

    我们在第一部分的文章中详细讲解了创建一个通知中心插件的整体过程.我们成功的在通知中心里面显示了新闻列表.但是截止到目前,我们还不能从通知中心的列表中查看新闻的详细内容.在这次的教程中,我们就以上次的教 ...

  4. 100个精选zencart扩展插件

    100个精选zencart扩展插件 特别推荐 1. 数据库备份 2. 产品横向布局. 3. 邮件订阅Newsletter Subscribe. 4. google 翻译google_translate ...

  5. jupyter notebook设置主题背景,字体和扩展插件

    windows上安装Anaconda (IPython notebook) Anaconda是一个包与环境的管理器,一个Python发行版,以及一个超过1000多个开源包的集合.它是免费和易于安装的, ...

  6. 认识Chrome扩展插件

    1.前言 现如今的时代,绝大多数人都要跟浏览器打交道的,说到浏览器那肯定是Chrome浏览器一家独大,具体数据请看 知名流量监测机构 Statcounter 公布了 7 月份全球桌面浏览器市场份额,主 ...

  7. 提高工作效率的神器:基于前端表格实现Chrome Excel扩展插件

    Chrome插件,官方名称extensions(扩展程序):为了方便理解,以下都称为插件. 我们开发的插件需要在浏览器里面运行,打开浏览器,通过右上角的三个点(自定义及控制)-更多工具-拓展程序-打开 ...

  8. iOS通知的整理笔记

    iOS通知用于高耦合界面的传值确实方便快捷. 需要实现模态弹出的视图控制器上,有一个视图控制器可以导航.这必定要将这个视图控制器的导航视图控制器naVC.view添加到模态弹出的视图控制器presen ...

  9. BlazeMeter发布chrome扩展插件,支持JMeter脚本创建

    BlazeMeter发布chrome扩展插件,支持JMeter脚本创建http://www.automationqa.com/forum.php?mod=viewthread&tid=3898 ...

随机推荐

  1. Go环境配置和GoModule

    Linux相关 Linux常用操作 mkdir directory --创建文件夹 vi file --创建文件,再关闭vim rm file --删除文件 rm -rf directory --递归 ...

  2. codeblocks中报错:'to_string' was not declared in this scope解决方案

    在windows下使用codeblocks(编译器采用MinGW)时,有时会遇到"'to_string' was not declared in this scope"的错误,这里 ...

  3. Docker 私服

    目录 什么是 Docker 私服? Docker 私服搭建 上传镜像至私服 从私服拉取镜像 什么是 Docker 私服? Docker 官方的 Docker Hub 是一个用于管理公共镜像的仓库,我们 ...

  4. 从SQL Server数据库导出SQL语句

    不同于直接 备份/恢复 或者 导入/导出 数据库操作. 新版本SQL Server客户端中还可以生成相对应的SQL语句. 非常方便与查看和与其他人共享. 连接上数据库后, 右击数据库, 选择 Gene ...

  5. Floodlight+Mininet的SDN实验平台搭建初探

    平台环境说明: Cpu:Intel Core 2 Duo T6570 Mem:4.00GB Os :Ubuntu 14.04 1.Floodlight Floodlight是一个比较成熟的sdn控制器 ...

  6. java-包与包之间的访问

    1 package face_package; 2 3 import face_packagedemoA.DemoA; 4 5 /* 包(package) 6 * 1,对类文件进行分类管理. 7 * ...

  7. thingsboard源码编译启动

    开发环境 不同的版本对应的开发环境不同(这里以3.3.3版本说明) jdk11+:参考jdk11+安装(win) Maven3.6+:Maven安装配置 Git:参考Git安装 IDEA: 参考IDE ...

  8. plsql 普通游标

    -- ①普通游标:操作步骤 边敲边想 学无止境 /* 游标:指针:内存中的一块数据缓冲区,上下文: 将查询到的结果集缓存起来,便于进行逐行定位处理. 使用完成后要及时关闭: 操作步骤? 1.定义游标 ...

  9. Docker版本Jenkins的使用

    一. 什么是Jenkins Jenkins是当前非常流行的一款持续集成工具,可以帮助大家把更新后的代码自动部署到服务器上运行. 二. 为什么用docker版的Jenkins Jenkins主要有三种安 ...

  10. python开发: linux进程打开的文件数

    1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 4 ''' 统计linux打开的文件数 ''' 5 6 import os 7 import sys ...