不同版本极光推送SDK集成各有差异,集成时一定要注意版本号,楼主已将博文更新成最新的SDK JPush v3.0.2. 各位童鞋先阅读下JPush v3.0.2的升级指南吧!
极光的最近更新
极光资源下载
JPush SDK v3.0.2 升级指南
更新时间
2017-02-13更新信息
修复:DNS解析失败带来的崩溃问题,提升稳定性升级提示
建议升级!
注意:支持 Xcode 8.0 以上版本 开启 bitcode。升级指南
1.注意 3.0.0及以上版本将不再支持处理器为i386的模拟器。
2.添加libresolv.tbd库(2.2.0及以上版本要求)
3.Xcode7 升级到 Xcode8,替换原先导入的 .dylib 框架为 .tbd (特别留意)
本博文修改历史
- 2017.03.25 ------------ JPush v3.0.2
- 2016.12.13 ------------ JPush v2.2.0
- 2016.09.28 ----------- JPush v2.1.9
简介
iOS10下,远程推送发生了变化,新增的UserNotifications.framework
将本地推送和远程推送整合在一起。 最近刚刚更新了Xcode8,自动创建证书和配置文件确实方便许多。琰君分享下以开发环境为例(非生产环境)在Xcode8下,快速集成极光推送并兼顾iOS10。
注意:极光的远程推送是免费的,并同时兼顾iOS,Android,Windows Phone三个平台,但相应的用户统计,终端统计等功能是不免费的。如果你需要用户统计,终端统计这些功能意味着需要付费才能使用。
参考链接
开发证书配置
APNs 推送原理及问题
iOS 推送全解析,你不可不知的所有 Tips!
接下来假设你都了解证书相关的,推送的一些概念和极光推送的知识。那么相信你应该知道需要一台iOS设备和一个苹果开发者帐号才能去体验远程推送。如果你清楚远程推送的原理,那可以直接从以下第2步开始。
集成步骤
- 远程推送原理
- Xcode8创建项目,配置自动创建
App ID
/证书
/配置文件
- 创建APNs 推送证书
- 在极光推送后台创建应用,并上传APNs 推送证书
- 项目中集成极光推送SDK
- notification payload 和远程推送类型
- 获取 APNs推送内容
- 极光推送后台发送远程推送测试
1. 远程推送原理
当iOS设备连网的情况下,iOS设备和苹果服务器建立了一个长链接,即便应用处于挂起和后台的状态,苹果可以给iOS设备中的应用发送通知。
概念
- iOS:iOS设备
- APNs Server:苹果服务器
- Your App: 自己的应用
- Your Server:自己的服务器
推送流程
- iOS 应用注册推送通知,iOS设备将设备的
UDID
和应用的Bundle ID
发送到苹果服务器。 - 苹果服务器将接收到的
UDID
和Bundle ID
加密生成一个deviceToken
,并返回给对应iOS应用。 - iOS应用将接收到的
deviceToken
发送到自己的服务器,服务器并保存。 - 自己的服务器需配置APNs 推送证书,当需要推送时,去后台查询推送目标设备的
deviceToken
,将notification payload
和deviceToken
一起发送给苹果服务器。notification payload
是一个JSON字典,包含着发给应用程序的数据,并且包含通知的类型(类型决定系统如何通知用户)。 - 苹果服务器通过
deviceToken
找到对应设备下的对应应用,推送消息。
说明
- 真机测试并且包含推送功能需要创建对应App ID/证书/配置文件, 这步可以用Xcode8 自动创建,而不需要到苹果开发者平台去创建。如果不是Xcode8,则需要去开发者平台申请,确保App ID包含推送通知服务,并且在Xcode中配置,保证真机测试即可。
- 我们自己的服务器需要配置 APNs 推送证书,同样的分为开发证书和生产证书。需要到苹果开发者平台去申请。
- 如果不借助第三方推送平台,我们需要完成推送流程中的1,3,4步。借助极光推送,那么我们只需要完成推送流程中的1,3步,但同样需要我们完成第4步中的申请APNs 推送证书,并且上传到极光推送平台。
2. Xcode8配置自动创建App ID/证书/配置文件
- 在Xcode8下,确保已经登录付费苹果开发者帐号。请开启Application Target的Capabilities->Push Notifications选项。
2.勾选自动管理App ID
/证书
/配置文件
3.检查Xcode自动创建的App ID
/证书
/配置文件
,保证下图中第4步App ID包含的远程推送服务。如果没问题就可以真机运行了。
3. 创建APNs 推送证书
- 登录开发者网站,并点击按钮创建证书
2.选择开发环境APNs 推送证书
点击右下角按钮创建
3.选择工程的App ID
4.上传证书请求文件,不知道的童鞋可参照开发证书配置
5.点击下载证书,并双击安装到钥匙串.
6.打开钥匙串,找到对应的APNs 推送证书,并选择右键导出包含私钥的证书。(确保证书左侧为向右的小箭头,导出的证书才会包含私钥.)
7.设置证书名字,并选择证书存放位置。
8.设置证书密码,可不填。极光推送支持证书设置密码,但像leanCloud
推送不支持证书设置密码,各位童鞋可按照实际情况来。最后输入电脑开密码,导出证书。
4. 在极光推送后台创建应用,并上传APNs 推送证书
1.登录极光推送平台,切换到控制台,并创建应用。接下来在应用信息中上传开发推送证书。生产推送证书配置类似,不做赘述。
- 核对应用的
Bundle ID
等信息是否正确.
5. 项目中集成极光推送SDK
极光推送最新版本3.0.2已支持CocoaPods导入。
- 方式一:CocoaPods导入,一句话搞定。
pod 'JPush', '3.0.2'
- 方式二:手动导入SDK和系统依赖库
jpush-ios-3.0.2.a jcore-ios-1.1.1.a JPUSHService.h
导入系统依赖库
CFNetwork.framework
CoreFoundation.framework
CoreTelephony.framework
SystemConfiguration.framework
CoreGraphics.framework
Foundation.framework
UIKit.framework
Security.framework
libz.tbd
Adsupport.framework (获取IDFA需要;如果不使用IDFA,请不要添加)
UserNotifications.framework(Xcode8及以上)
libresolv.tbd (JPush 2.2.0及以上版本需要)
3. AppDelegate.m 配置
导入以下头文件
import "JPUSHService.h"
// 如果需要使用idfa功能所需要引入的头文件(可选)
import <AdSupport/AdSupport.h>
ifdef NSFoundationVersionNumber_iOS_9_x_Max
import <UserNotifications/UserNotifications.h>
endif
并且遵守`<JPUSHRegisterDelegate>`协议
@interface AppDelegate ()<JPUSHRegisterDelegate>
@end
注册远程推送,初始化极光推送SDK。
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//-------------注册远程推送
//notice: 3.0.0及以后版本注册可以这样写,也可以继续用之前的注册方式
JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound;
[JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
//-------------极光推送SDK初始化
BOOL isProduction = NO;// NO为开发环境,YES为生产环境
//广告标识符 如果没有使用IDFA直接传nil
NSString *advertisingId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
[JPUSHService setupWithOption:launchOptions appKey:@"极光推送AppKey"
channel:nil
apsForProduction:isProduction
advertisingIdentifier:advertisingId];
return YES;
}
以上是注册远程推送极光版本,很简洁。下面是注册远程推送系统版本,可以参考下。
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CGFloat version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version >= 10.0)
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:UNAuthorizationOptionCarPlay | UNAuthorizationOptionSound | UNAuthorizationOptionBadge | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(@" iOS 10 request notification success");
}else{
NSLog(@" iOS 10 request notification fail");
}
}];
}
else if (version >= 8.0)
{
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert categories:nil];
[application registerUserNotificationSettings:setting];
}else
{ //iOS <= 7.0
UIRemoteNotificationType type = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:type];
}
//注册通知
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
将苹果服务器返回的`deviceToken`,上传到极光推送服务器。
-(void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
[JPUSHService registerDeviceToken:deviceToken];
}
注册远程通知失败,比如没有联网的状态下。
-(void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(@"did Fail To Register For Remote Notifications With Error: %@", error);
}
#####6.notification payload 和远程推送类型
发送远程推送的服务器发送给APNs的每个通知都包含payload。 payload是一个JSON字典,包含要发送到应用程序的任何自定义数据,并包含有关推送类型的信息(推送类型决定系统如何通知用户)。
远程推送分为普通推送,后台推送,静默推送三种方式。以下以远程推送的类型来讨论下payload的构造。以下只考虑iOS7之后的操作系统。
- 普通推送
- payload 构造:包含声音、内容、角标、自定义字段。
{
aps = {
alert = "显示内容";//alert对应的值也可以是字典,字典中body键的值对应显示内容
badge = 1; // App 角标,可推送 n、+n、-n 来实现角标的固定、增加、减少
sound = default; // 推送声音,默认系统三全音,如需使用自己的声音,需要将声音文件拖拽&拷贝至 Xcode 工程目录任意位置,并在推送时指定其文件名
};
proNo = "tb_pro_no_id249349874"; // 自定义字段
DesVc = "ProViewController";
}
- 处于未启动,系统会显示通知,点击通知横幅启动,在以下方法中获取通知内容:
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- 处于后台,系统会显示通知,但不会通知对应应用(即应用的方法不会被调用)。
- 处于前台,iOS10之后会显示通知。(iOS10之前会不会展示通知,楼主也记不住了😭)在以下方法中获取通知内容:
- iOS7 ~ iOS9
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler
- iOS10 after (UNUserNotificationCenterDelegate中的代理方法)
-(void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
- 后台推送
- 必须在 Xcode 工程中 TARGETS – Capabilities – Background Modes 中开启Remote notifications功能。
- payload构造:必须携带 "content-available" = 1,必须携带 alert中的显示信息、badge、sound 中 至少 1 个字段。
{
aps = {
alert = "显示内容";//alert对应的值也可以是字典,字典中body键的值对应显示内容
badge = 1;
"content-available" = 1; // 必带字段
sound = default;
};
key1 = value1;
}
- 处于未启动,同上述普通推送一致。
- 处于后台或者挂起,系统会显示通知。通过下述获取通知内容,你的应用会在后台启动(如果应用为挂起状态,则唤醒它,处于后台状态),将有30秒的时间进行处理通知或者下载数据等操作。
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler
- 处于前台, 系统会显示通知。可通过以下方法获取内容:
- iOS7 after
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler
- 注:iOS10 之后除了会调用上面的方法,还会调用此方法 (UNUserNotificationCenterDelegate中的代理方法)
-(void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
- 静默推送
- 系统不会显示通知,用户不会有任何察觉。
- payload构造:必须携带 "content-available" = 1。必须不携带 alert中的显示内容、badge、sound。
{
aps = {
alert = "";//alert对应的值也可以为字典,字典中不能包含body键值对。
"content-available" = 1; // 必带字段
};
key1 = value1;
}
- 处于未启动,获取不到通知内容
- 处于后台,iOS7 之后你的应用会在后台启动(如果应用为挂起状态,则唤醒它,处于后台状态),将有30秒的时间进行处理通知或者下载数据等操作。可通过下述方法获取内容:
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler
- 处于前台, iOS7 之后可通过下述方法获取内容:
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler
#####7.获取 APNs(通知) 推送内容
iOS 设备收到一条推送(APNs),用户点击推送通知打开应用时,应用程序根据状态不同进行处理,需在 AppDelegate 中的以下方法中添加代码以获取apn内容。
- 如果 App 状态为未运行,此函数将被调用,如果launchOptions包含UIApplicationLaunchOptionsRemoteNotificationKey表示用户点击apn 通知导致app被启动运行;如果不含有对应键值则表示 App 不是因点击apn而被启动,可能为直接点击icon被启动或其他。
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
// apn 内容获取:
NSDictionary *remoteNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey]
}
2.基于iOS 6 及以下的系统版本,如果 App状态为正在前台或者点击通知栏的通知消息,那么此函数将被调用,并且可通过AppDelegate的applicationState是否为UIApplicationStateActive判断程序是否在前台运行。
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo{
}
3.此方法会在以下几种情况下调用
- iOS7 ~ iOS9 前台接收普通推送。
- iOS7之后开启Background Mode Remote Notification特性,在前台或者后台接收到后台推送和静默推送。
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {
[JPUSHService handleRemoteNotification:userInfo];
NSLog(@"iOS7及以上系统,收到通知:%@", [self logDic:userInfo]);
completionHandler(UIBackgroundFetchResultNewData);
}
-(NSString *)logDic:(NSDictionary *)dic {
if (![dic count]) {
return nil;
}
NSString *tempStr1 =
[[dic description] stringByReplacingOccurrencesOfString:@"\u"
withString:@"\U"];
NSString *tempStr2 =
[tempStr1 stringByReplacingOccurrencesOfString:@""" withString:@"\""];
NSString *tempStr3 =
[[@""" stringByAppendingString:tempStr2] stringByAppendingString:@"""];
NSData *tempData = [tempStr3 dataUsingEncoding:NSUTF8StringEncoding];
NSString *str =
[NSPropertyListSerialization propertyListFromData:tempData
mutabilityOption:NSPropertyListImmutable
format:NULL
errorDescription:NULL];
return str;
}
4.基于iOS 10及以上的系统版本,
原`[application: didReceiveRemoteNotification:]`将会被系统废弃,
由新增`UserNotifications.framework`中的以下两个方法替代。
[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:]
[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]
在极光推送SDK2.1.9版本以后可实现SDK封装的JPUSHRegisterDelegate协议方法,适配iOS10新增的delegate协议方法。
即以下两个方法:
ifdef NSFoundationVersionNumber_iOS_9_x_Max
pragma mark- JPUSHRegisterDelegate
//前台收到推送,可以采取必要的措施处理通知和更新APP的内容。
-(void)jpushNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
NSDictionary * userInfo = notification.request.content.userInfo;
UNNotificationRequest *request = notification.request; // 收到推送的请求
UNNotificationContent *content = request.content; // 收到推送的消息内容
NSNumber *badge = content.badge; // 推送消息的角标
NSString *body = content.body; // 推送消息体
UNNotificationSound *sound = content.sound; // 推送消息的声音
NSString *subtitle = content.subtitle; // 推送消息的副标题
NSString *title = content.title; // 推送消息的标题
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
NSLog(@"iOS10 前台收到远程通知:%@", [self logDic:userInfo]);
}
// 指定系统如何提醒用户,有Badge、Sound、Alert三种类型可以设置
// 如果不需提醒可传UNNotificationPresentationOptionNone
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert);
}
//当用户点击了通知的某个操作,需要进行相应处理,如跳转到某个界面
-(void)jpushNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSDictionary * userInfo = response.notification.request.content.userInfo;
UNNotificationRequest *request = response.notification.request; // 收到推送的请求
UNNotificationContent *content = request.content; // 收到推送的消息内容
NSNumber *badge = content.badge; // 推送消息的角标
NSString *body = content.body; // 推送消息体
UNNotificationSound *sound = content.sound; // 推送消息的声音
NSString *subtitle = content.subtitle; // 推送消息的副标题
NSString *title = content.title; // 推送消息的标题
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
NSLog(@"iOS10 收到远程通知:%@", [self logDic:userInfo]);
}
// 让系统知道你已处理完通知。
completionHandler();
}
endif
#####8. 极光推送后台发送远程推送测试
1.登录`极光推送`,切换到控制台,并点击对应的应用,点击推送按钮
![点击推送按钮](http://upload-images.jianshu.io/upload_images/790038-ce63654e0f2dafec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![点击发送通知](http://upload-images.jianshu.io/upload_images/790038-e67a3d8e1f5eec8e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2.设置推送内容
![设置推送内容](http://upload-images.jianshu.io/upload_images/790038-86e85fb6524a99e9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
选择推送环境iOS开发环境,目标人群,发送时间。再点击可选设置设置消息的具体内容。
![选择推送环境](http://upload-images.jianshu.io/upload_images/790038-b8d4bb9b0e23c641.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
3.设置消息具体内容。
![设置推送内容](http://upload-images.jianshu.io/upload_images/790038-f8e05e4ad5093b25.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
4.iOS设备接收到远程推送
![iOS设备接收到远程推送](http://upload-images.jianshu.io/upload_images/790038-9969a3408695827e.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
以下为打印的通知内容。
{
"_j_msgid" = 3017423712;
aps = {
alert = {
body = "你爱谈天,我爱笑~~";
subtitle = "每天坚持1小时,会有大收获。";
title = "天天";
};
badge = 100;
sound = default;
};
}
5.推送历史可以在这里看得到,但有延迟,可能远程推送已接收到,推送历史数据还没有更新到最新。
![推送历史](http://upload-images.jianshu.io/upload_images/790038-994708e85592d06b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
关于Xcode8下集成极光远程推送的简单介绍,到这里就结束了。