我的项目是基于极光推送的
证书都是配置好的 自动配置即可Automatically manage signing
推送模拟都是自己在极光官网后台管理中模拟推送
新需求就是推送栏有图片 长按可以查看图片
推送效果
11615785264_.pic_hd.jpg 21615785265_.pic_hd.jpg
推送原理(面试被问到这个问题很尴尬)
苹果的推送服务通知是由自己专门的推送服务器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.pngiOS 10之前,iOS推送只能实现文字消息。
iOS10之后,苹果官方新增了一些特性,其中包括新的推送方式----推送拦截(Service Extension),这种推送方式允许iOS开发者对接收到的推送消息进行一定的处理,以便达到自己想要的效果。
创建Extension
-
target
image.png -
Notification Service Extension
image.png -
启动这个计划
image.png -
效果图
image.png
-
在info.plist文件中添加http协议防止图片视频资源加载不了
image.png
模拟推送
iOS 10 新增的 Notification Service Extension 功能,用 mutable-content 字段来控制。
若使用 Web 控制台,需勾选 “可选设置”中 mutable-content 选项;若使用 RESTFul API 需设置 mutable-content 字段为 true。
未勾选mutable-content
image.png 31615802277_.pic_hd.jpg控制台打印 (手动点击通知栏 打印的推送通知)
{
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.png 41615802449_.pic_hd.jpg发现和之前未勾选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中 有主动创建拦截处理通知
- (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.png image.png代码
- (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.png
image.png
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.png
自定义UI contentExtension(长按查看通知界面)
image.png image.png image.pngUNNotificationExtensionDefaultContentHidden 为YES 隐藏系统UI
然后设置在NotificationService.m
中设置categoryIdentifier
self.bestAttemptContent.categoryIdentifier = @"myNotificationCategory";
上架报错?
提示要配置证书 展示配置把
配置证书这边
image.png
先配置Identifiers
image.png
配置Profiles
image.png
点击安装profiles 证书不需要 就之前原工厂证书即可
image.png
打包
WX20210323-222741.png
网友评论