iOS10富文本推送通知 | 大专栏

Table of Contents

  • 1. Xcode推送开关

  • 2. APNs推送格式定义

    • 2.1. 普通推送的格式

    • 2.2. iOS10富文本推送扩展字段

  • 3. 推送消息处理

    • 3.3.1. 暂存处理资源

    • 3.3.2. 解析图片地址

    • 3.3.3. 下载图片

    • 3.3.4. 缓存图片内容

    • 3.3.5. Attachment封装

    • 3.3.6. 图片推送样式

    • 3.3.7. Service Time Expire的回调处理

    • 3.1. 新建一个Notification Service Extension

    • 3.2. bundle identifier命名

    • 3.3. NotificationService类

  • 4. 推送消息界面

    • 4.1. 新建Notification Content Extention

    • 4.2. 自定义界面

    • 4.3. 自定义界面对应的类

    • 4.4. category设置

    • 4.5. 最终效果

    • 4.6. 其他需要注意的点

  • 5. 参考资料

苹果在iOS10系统时推出了UNNotification用户消息framework,这个framework相比以往的Remote Notification和Local Notification,增加了不少功能。
列出iOS10 Notification的新功能。
这篇文章我们讨论的是新增的Rich Notification部分。

1 Xcode推送开关

  • App远程推送开关:
    如果你的App要使用推送功能,首先需要打开App的远程推送开关。

  • 打开推送的后台模式:
    iOS7开始,苹果提供了后台接收远程消息的功能,进程在后台存活时也能接收到消息

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0);

2 APNs推送格式定义

2.1 普通推送的格式

以下是一个普通的APNs推送消息收到后的消息体,包含了title, body, sound, badge等基本的消息元素。

{"aps": {"alert": {"title": "Wanda Wealth Big Gift!","body": "Wanda Wealth will give you 100,000 bonus if you participate our Moon Lover's Activity!"},"sound": "default","badge": 10
    }
}

2.2 iOS10富文本推送扩展字段

富文本推送本质上是允许App改变推送消息的UI样式,所以需要在aps消息体里加入字段mutable-content。

category字段表示该条消息属于哪个类别,将会由相对象的Notification Service来做相应的处理,iOS10后允许开发者建立多个Notification Service来处理相应APNs消息体。

attachment-image是我们自定义的字段,表示该条推送附带的图片URL地址。你也可以根据自己业务逻辑自定义字段语义,比如可以定义attach-url, attach-type,这样可以区别是附带的图片还是视频。

{"aps": {// alert, sound, badge, ...// ......"mutable-content": 1,"category": "push-message-category",
    }"attachment-image": "https://caifu.xinshengdaxue.com/assets/logo.png"}

3 推送消息处理

推送消息收到后,我们需要先下载attachment-image,保存在缓存中。苹果提供了Notification Service Extension的消息推送服务扩展,开发者可以在这里拿到消息体,解析得到attachment-image自定义字段后作下载缓存处理。

3.1 新建一个Notification Service Extension

下图展示了新建的过程,在Xcode里点击File->New->Target->Notficiation Service Extension

3.2 bundle identifier命名

在命名BundleID的时候需要注意的是,其前缀最好包含App Target的bundleID。

3.3 NotificationService类

当新建好Extension后,Xcode为我们新建了NotificationService类,它继承了UNNotificationServiceExtension框架类。
该类有两个回调方法,第一个是接收到推送消息后的回调,用于下载富文本内容。

serviceExtensionTimeWillExpire提醒App,Extension将要结束,我们可以在这里做一些暂停下载,标记标志位等工作,以等下次App重新唤醒的时候在UIApplicationDelegate的回调中继续下载。

@interface UNNotificationServiceExtension : NSObject// Call contentHandler with the modified notification content to deliver. If the handler is not called before the service's time expires then the unmodified notification will be delivered.// You are expected to override this method to implement push notification modification.- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *contentToDeliver))contentHandler;// Will be called just before this extension is terminated by the system. You may choose whether to override this method.- (void)serviceExtensionTimeWillExpire;@end

3.3.1 暂存处理资源

didReceiveRemoteNotification回调提供了contentHandler回调block,调用后系统会知道这条消息是否已被处理。由于图片、文件或视频的下载可能是异步下载,所以需要暂存这些处理资源。

self.contentHandler = contentHandler;self.bestAttemptContent = [request.content mutableCopy];

3.3.2 解析图片地址

我们先要从UNNotficationRequest参数中解析到attachment-image内容

NSString *attachUrl = [request.content.userInfo objectForKey:@"attachment-image"];

3.3.3 下载图片

以下的代码使用的是同步下载方案,仅为Demo代码,后续上生产环境需要使用异步代码完成。

- (UIImage *)getImageFromUrl:(NSString *)url {
    NSLog(@"NotificationService, getImageFromUrl: %@", url);UIImage *result;NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
    result = [UIImage imageWithData:data];return result;
}

3.3.4 缓存图片内容

下载好图片后,需要缓存图片内容。其中uuidStr是缓存图片名,saveImage将UIImage存储到Document目录下(其实应当存在Cache)目录下。

NSString *uuidStr = @"2B3CB2BD-1626-4192-A72A-0FA3B1A02279";NSString *localPath = [self saveImage:image withFileName:uuidStr ofType:@"png" inDirectionary:docPath];if (localPath.length > 0) {NSURL *localPathUrl = [NSURL URLWithString:[@"file://" stringByAppendingString:localPath]];

 }

3.3.5 Attachment封装

图片下载后,就可以封装成UNNotificationAttachment供系统回调调用。

UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:kPushNotificationImageAttachment URL:localPathUrl options:nil error:nil];if (attachment) {self.bestAttemptContent.attachments = @[attachment];
}self.contentHandler(self.bestAttemptContent);

3.3.6 图片推送样式

经过上面几步操作,我们最终在系统消息中心显示了带图片的推送样式。

3.3.7 Service Time Expire的回调处理

以下代码简单地处理了Time Expire回调,简单地将bestAttemptContent回调给系统。在这里可能图片并没有下载完全,所以bestAttempContent仅仅是文字的显示。

- (void)serviceExtensionTimeWillExpire {self.contentHandler(self.bestAttemptContent);
}

4 推送消息界面

iOS10的Notification Content Extension为开发者提供了自定义force touch推送消息后展开的UI界面的能力。我们可以展示文字、图片、视频,以及Notification Action,如消息回复、订阅、稍后阅读等。

4.1 新建Notification Content Extention

下图展示了新建的过程,在Xcode里点击File->New->Target->Notficiation Content Extension

4.2 自定义界面

Extension创建后,其Info.plist里指定了NSExtensionMainStoryboard字段,表示自定义界面使用相应名字的storyboard;下图是一个定制化的界面,显示一张正方形的图片:

4.3 自定义界面对应的类

上面的storyboard对应的类是NotificationViewController,我们在它的didReceiveNotification:的回调函数中渲染界面。

UNNotification其实就是上面的Notification Service下载图片后封装成Attachment后塞回给系统,系统再封装成一个UNNotification,传给NotificationViewController。开发者只需要从UNNotification中取出Attachment中的图片地址,生成UIImage后显示即可。

- (void)didReceiveNotification:(UNNotification *)notification {
    NSLog(@"NotificationViewController, didReceiveNotification: %@", notification.description);UNNotificationContent *content = notification.request.content;UNNotificationAttachment *attachment = content.attachments.firstObject;if (attachment.URL.startAccessingSecurityScopedResource) {self.imageView.image = [UIImage imageWithContentsOfFile:attachment.URL.path];
    }
}

4.4 category设置

Notification Service负责下载,Notification Content负责展示。category的作用是分发不同的推送消息给相应的Notification Content。
category需要在Info.plist中进行配置,设置UNNotificationExtensionCategory的值为上面提到过的aps中的相应值,push-message-category。

4.5 最终效果

我们使用了李笑来老师 财富自由之路 网站的favicon,也是他的头像。下图就是消息force touch后展示的样子。
你可以根据自己App的设计来重新布局你的消息展示形式。

4.6 其他需要注意的点

我们在这里仅仅是给出了富文本消息最简单的示例,有一些point可能需要你自己去查询研究。

  • 自定义Notification Content的时候,你可以不使用Storyboard,直接使用代码进行布局。需要修改Info.plist中的内容

  • Storyboard中我们没有显示消息体,而force touch后,我们看到了消息体。需要研究一下保留展示原消息体的配置项

  • 以上代码使用了同步下载图片的策略,可以改成异步下载策略

5 参考资料

(0)

相关推荐