最近工作中新增一个告警推送带图片的需求,要求在云端服务器向极光推送图片地址,APP在收到推送消息以后能够将地址对应的图片下载完成并显示在推送栏右侧,经过一段时间对极光推送官方文档和iOS10新特性Service Extension的研究,终于实现了该功能的开发。由于是初次使用此功能,遇到不少问题,为做记录以及方便大家查阅,故写下这篇博客,若有不恰当之处敬请留言指导,不胜感激,话不多说,开始正文!

一、极光推送的流程介绍

通常,后台推送比较常见,本文仅介绍关于后台极光推送的实现流程。如下图红色箭头所示

image.png

1、云服务器调用极光的接口向极光发送消息,极光收到消息后会将消息发送给苹果的APNs服务器,苹果再根据唯一标示找到手机,手机收到推送消息后,会在屏幕上方弹出推送消息。

2、iOS 10以前,iOS的推送只能实现推送文字消息,这时候就需要云服务器将推送的内容发送给极光,APP展示在界面上。iOS 10以后,苹果官方新增了一些特性,其中包括新的推送方式----推送拦截(Service Extension),这种推送方式允许iOS开发者对接收到的推送消息进行一定的处理,以便达到自己想要的效果。

2、Service Extension介绍

image.png

如上图所示,在iOS 10以后,在APNs与APP之间增加了一个扩展,这意味着在APNs到达我们的设备之前,还会经过一层允许用户自主设置的Extension服务进行处理,为APNs增加了多样性,在这个Extension中,我们可以图片、音频(比如支付宝的到账提醒语音),我们甚至可以修改显示的文字消息(意义不大,如果需要修改,直接让服务器去修改推送的内容就可以了)。

3、Service Extension集成介绍

极光推送的内容此处忽略,需要学习的请参考https://docs.jiguang.cn/jpush/client/iOS/ios_guide_new/
1、新建Service Extension,File->New->Target

image.png

image.png

需要注意的一点是,这是一个新的target,bundle ID与主APP不同,它是主APP的一个扩展,必须是主APP的bundle ID拼上target的名字。
创建完成后,会多一个target,如下图:

image.png

2、此时主工程需要如下配置:

image.png

3、对Extension做如下配置:

image.png

4、将极光的库导入工程并引入依赖库:

image.png

5、接下来就需要为新的target制作证书了,从APP IDs 到 Provisioning Profiles, 配置好开发环境、生产环境的Provisioning Profile之后,依次选择对应的证书即可,关于如何制作证书,这里不赘述,请出门右拐找度娘。
证书配置完毕后,APP的准备工作算是完成了,服务器需要将字段:"mutable -content" 设置为true后再发给极光,具体的集成步骤,请服务器人员自行参考极光官网。

二、Service Extension target编码

进入到Xcode自动给你创建的.m文件中,会发现有2个方法。

  • didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *contentToDeliver))contentHandler

  • serviceExtensionTimeWillExpire

第一个方法就是我们用于拦截推送消息后,自定义消息内容的方法。第二个方法是对第一个方法的补救。第二个方法会在过期之前进行回调,此时你可以对你的APNs消息进行一下紧急处理,比如多媒体文件过大,下载的时间过长,会直接调用此方法。

注意:媒体资源文件不宜过大,否则耗时过长,无法达到拦截效果

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {self.contentHandler = contentHandler;self.bestAttemptContent = [request.content mutableCopy];
/*
*  解析图片的地址
*  收到的字典数据结构并不是和服务器约定好的,为了通用性,此处递归解析字典
*/ NSString *imgUrl = [self getURLForUserInfo:self.bestAttemptContent.userInfo];if (imgUrl) {//downloadNSURL *fileURL = [NSURL URLWithString:imgUrl];[self downloadAndSave:fileURL handler:^(NSString *localPath) {if (localPath) {UNNotificationAttachment * attachment = [UNNotificationAttachment attachmentWithIdentifier:@"myAttachment" URL:[NSURL fileURLWithPath:localPath] options:nil error:nil];self.bestAttemptContent.attachments = @[attachment];}//此方法为极光SDK中的用于上传appKey的方法[self apnsDeliverWith:request];}];}else{[self apnsDeliverWith:request];}
}

此处收到的字典,但字典的数据结构并不是与云服务器约定好的结构,此问题咨询过极光的工作人员,并未给出合理的解释,此处为了规避数据结构异常导致的问题,采用递归解析的方式获取地址。解析方法如下:

- (NSString *)getURLForUserInfo:(NSDictionary *)userInfo {__block NSString *url = nil;__block __weak __typeof(&*self)weakSelf = self;[userInfo enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {if ([key containsString:@"url"]) {*stop = YES;url = obj;}if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]]) {url = [weakSelf getURLForUserInfo:obj];}}];return url;
}

由于这是扩展的target,无法使用主工程的网络请求库,需要使用原生的网络请求方法下载资源文件:

- (void)downloadAndSave:(NSURL *)fileURL handler:(void (^)(NSString *))handler {NSURLSession * session = [NSURLSession sharedSession];NSURLSessionDownloadTask *task = [session downloadTaskWithURL:fileURL completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {NSString *localPath = nil;if (!error) {//临时文件夹路径,APP没有运行时会自动清除图片,不会占用内存NSString * localURL = [NSString stringWithFormat:@"%@/%@", NSTemporaryDirectory(),fileURL.lastPathComponent];if ([[NSFileManager defaultManager] moveItemAtPath:location.path toPath:localURL error:nil]) {localPath = localURL;}}handler(localPath);}];[task resume];}

资源文件下载失败,紧急处理:

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

三、Service Extension target调试

编码完成后,通常需要调试,主要涉及两个方面,一个是扩展工程的在线调试,另一个是极光推送的编译环境调试。

1、极光在线调试

进入极光主页,进入如下界面:

image.png

配置相关信息,需要注意的一点是,Service Extension target需要勾选下图中的选项:

image.png

点击推送后,APP即可收到后台推送消息。如果需要显示图片,则在附件字段一栏,设置好键值对。

2、扩展工程在线调试

首先需要运行主工程文件,等主工程文件运行起来后点击下图操作,过一段时间会出现你的扩展工程(有时候会出不来,感觉像是Xcode的bug),当你接受的推送后,会在你的扩展工程中的断点处停下。

扩展工程调试.png

3、字段调试

如果2中所提的调试方法无法使用断点,可以采用修改推送内容的方式来调试,如下:

self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [NotificationService]", self.bestAttemptContent.title];

此时,你收到的推送消息将会拼接上[NotificationService],如果是这种格式显示的,那么恭喜你,你的扩展拦截是OK的;如果收到的没有拼接上,那么,说明你拦截失败,需要考虑你的集成步骤是否正确,或者是证书的生成是否OK。

附上一张带图片推送的图片

//

//  NotificationService.m

//  extension

//

//  Created by admin10 on 2019/2/19.

//  Copyright © 2019年 sun. All rights reserved.

//

#import "NotificationService.h"

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);

@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {

self.contentHandler = contentHandler;

self.bestAttemptContent = [request.content mutableCopy];

/*

*  解析图片的地址

*  收到的字典数据结构并不是和服务器约定好的,为了通用性,此处递归解析字典

*/

NSString *imgUrl = [self getURLForUserInfo:self.bestAttemptContent.userInfo];

if (imgUrl) {

//download

NSURL *fileURL = [NSURL URLWithString:imgUrl];

[self downloadAndSave:fileURL handler:^(NSString *localPath) {

if (localPath) {

UNNotificationAttachment * attachment = [UNNotificationAttachment attachmentWithIdentifier:@"myAttachment" URL:[NSURL fileURLWithPath:localPath] options:nil error:nil];

self.bestAttemptContent.attachments = @[attachment];

}

//此方法为极光SDK中的用于上传appKey的方法

[self apnsDeliverWith:request];

}];

}else{

[self apnsDeliverWith:request];

}

}

- (NSString *)getURLForUserInfo:(NSDictionary *)userInfo {

__block NSString *url = nil;

__block __weak __typeof(&*self)weakSelf = self;

[userInfo enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {

if ([key containsString:@"url"]) {

*stop = YES;

url = obj;

}

if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]]) {

url = [weakSelf getURLForUserInfo:obj];

}

}];

return url;

}

- (void)downloadAndSave:(NSURL *)fileURL handler:(void (^)(NSString *))handler {

NSURLSession * session = [NSURLSession sharedSession];

NSURLSessionDownloadTask *task = [session downloadTaskWithURL:fileURL completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

NSString *localPath = nil;

if (!error) {

//临时文件夹路径,APP没有运行时会自动清除图片,不会占用内存

NSString * localURL = [NSString stringWithFormat:@"%@/%@", NSTemporaryDirectory(),fileURL.lastPathComponent];

if ([[NSFileManager defaultManager] moveItemAtPath:location.path toPath:localURL error:nil]) {

localPath = localURL;

}

}

handler(localPath);

}];

[task resume];

}

- (void)serviceExtensionTimeWillExpire {

// Called just before the extension will be terminated by the system.

// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.

self.contentHandler(self.bestAttemptContent);

}

@end

作者:小蜗牛吱呀之悠悠
链接:https://www.jianshu.com/p/c0a65526e653
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

iOS极光推送带图片模式(Service Extension)推送右侧出现图片相关推荐

  1. uniapp轻松集成极光推送自定义消息+通知 Android极光 IOS极光 两行代码集成极光SDK

    ###[前言] 极光推送(JPush)在为开发者提供基础推送服务的同时,还提供了用户精准标签.用户分群.地理围栏.应用内消息.智能发送策略.智能促活等服务能力,可有效提升消息的送达率.展示率和点击率, ...

  2. 极光推送:java后台向APP推送消息(android,ios极光推送消息)

    Maven添加依赖 <!--极光推送--><dependency><groupId>cn.jpush.api</groupId><artifact ...

  3. iOS原生推送(APNS)进阶iOS10推送图片、视频、音乐

    代码地址如下: http://www.demodashi.com/demo/13208.html 前言 我们首先要在AppDelegate里面进行iOS的适配,可以参考这篇文章 iOS原生推送(APN ...

  4. 极光推送:后台向APP:android,ios极光推送消息

    1. 添加依赖 //jpushcompile group: 'cn.jpush.api', name: 'jpush-client', version: '3.3.4' 2. 注册极光用户 //APP ...

  5. iOS极光推送的使用说明

    iOS SDK 教程 iOS SDK 调试指南 iOS 调试思维导图 确认证书 请到"应用详情页面"确认证书可用性: 开发环境测试 在对 JPush iOS 开发环境进行测试前,请 ...

  6. Apple Push Notification Service(苹果推送服务)

    https://developer.apple.com/library/IOS/documentation/NetworkingInternet/Conceptual/RemoteNotificati ...

  7. IM篇 I (╯‵□′)╯︵┻━┻ 极光?个推?腾讯云?第三方推送平台该怎么选?

    推送的意义 「推送机制」为我们提供了一条可以「直接触达用户」的路径,使移动设备终端的「全时信息传播」成为可能,是C端运营人员提高用户活跃度.提高应用留存率的常规途径之一,以助于其「更高效地完成运营目标 ...

  8. 一篇文章带你了解APP PUSH推送机制

    本文为PMCAFF专栏作者卓别木出品 写作目的: 本文主要讲解关于APP PUSH的流程.机制及相关经验,一是为了方便各位可以针对APP迅速制定PUSH消息推送方案,实现0到1的推送功能搭建,二是可以 ...

  9. Andriod之使用极光推送自定义消息打造个性的消息推送效果

    没必要重复造轮子,吸收别人的精华,站在巨人的肩膀上,才能走得更远,如果技术不能带来利润,狗屁都不如,好了,介绍下极光推送吧,我们项目里面用的是个推,先把这个极光推送的转载好,再来写个推的推送,原理差不 ...

最新文章

  1. 陌陌一面,为什么SpringBoot的 jar 可以独立运行?
  2. (邓爱萍)类对象-this关键字
  3. SSH服务审计工具ssh-audit
  4. 皮一皮:大家对自己的定位都挺准的...
  5. 【产品干货】衡量移动APP“价值”的9个重要的KPI指标
  6. Linux id指令
  7. java 字符串 数组互转
  8. boost::multiprecision模块测试 cpp_dec_float_50 是否符合我们的 概念要求
  9. Chrome source code map - fail - cannot debug
  10. WebBrowser!
  11. 第三十八期:美国数据隐私保护法案来临,明年1月生效,现仅2%企业合规
  12. 插画素材 | 冬天很冷,看到它内心就暖了!
  13. js Date 日期函数
  14. MFC程序设计——标尺的例子
  15. 介绍一款免费的词典与文本翻译软件-灵格斯 lingoes
  16. 淘宝客如何赚钱?为什么很多人做淘宝客赚不到钱?
  17. hosts文件是什么? 以及在各个系统中(Windows、Mac、Linux)的hosts文件在哪里?
  18. verilog增量式编码器
  19. 安卓recovery系统详解
  20. Vue3.2——父传子、子传父

热门文章

  1. c语言真随机,怎样让c语言中的随机函数真正随机?
  2. 咖说 | 中国央行 DCEP 和 Libra 暗战三回合
  3. 从渣渣辉到送你一只鲲 游戏买量高成本僵局如何破?!
  4. dcloud管理收货地址mui
  5. php mysql 网站 任务书_办公用品网上商城的设计与实现PHP+MYSQL任务书
  6. 前端给身份证以及电话做敏感加密
  7. (九)项目三日志 三
  8. linux中软件触发中断SGI(IPI)的使用
  9. 机器人庄园作文_友谊伴我成长作文400字
  10. day 026 QQ