我的项目是基于极光推送的
证书都是配置好的 自动配置即可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介绍
imageiOS 10之前,iOS推送只能实现文字消息。
iOS10之后,苹果官方新增了一些特性,其中包括新的推送方式----推送拦截(Service Extension),这种推送方式允许iOS开发者对接收到的推送消息进行一定的处理,以便达到自己想要的效果。
创建Extension
-
target
image -
Notification Service Extension
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中 有主动创建拦截处理通知
- (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 imageUNNotificationAction
/*
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 imageUNNotificationExtensionDefaultContentHidden 为YES 隐藏系统UI
然后设置在NotificationService.m
中设置categoryIdentifier
self.bestAttemptContent.categoryIdentifier = @"myNotificationCategory";
上架报错?
提示要配置证书 展示配置把
配置证书这边
先配置Identifiers
image配置Profiles
image点击安装profiles 证书不需要 就之前原工厂证书即可
image打包
image作者:守护地中海的花
链接:https://www.jianshu.com/p/966da14e68e3
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
网友评论