前言
iOS10下,远程推送发生了变化,新增的UserNotifications.framework
将本地推送和远程推送整合在一起。 最近刚刚更新了Xcode8,自动创建证书和配置文件确实方便许多。琰君分享下以开发环境为例(非生产环境)在Xcode8下,快速集成极光推送并兼顾iOS10。
注意:极光推送的远程推送是免费的,但相应的用户统计,终端统计等功能是不免费。如果你需要用户统计,终端统计这些功能意味着需要付费才能使用。
参考链接
开发证书配置
APNs 推送原理及问题
iOS 推送全解析,你不可不知的所有 Tips!
接下来假设你都了解证书相关的,推送的一些概念和极光推送的知识。那么相信你应该知道需要一台iOS设备和一个苹果开发者帐号才能去体验远程推送。如果你清楚远程推送的原理,那可以直接从以下第2步开始。
集成步骤
- 远程推送原理
- Xcode8创建项目,配置自动创建
App ID
/证书
/配置文件
- 创建APNs 推送证书
- 在极光推送后台创建应用,并上传APNs 推送证书
- 项目中集成极光推送SDK
- 获取 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
,将消息和deviceToken
一起发送给苹果服务器。 - 苹果服务器通过
deviceToken
找到对应设备下的对应应用,推送消息。
说明
- 我们的应用真机测试需要创建对应App ID/证书/配置文件, 这步可以用Xcode8 自动创建,而不需要到苹果开发者平台去创建。如果不是Xcode8,则需要去开发者平台申请,并且在Xcode配置,保证真机测试即可。
- 我们自己的服务器需要配置 APNs 推送证书,同样的分为开发证书和生产证书。需要到苹果开发者平台去申请。
- 如果不借助第三方推送平台,我们需要完成推送流程中的1,3,4步。借助极光推送,那么我们只需要完成推送流程中的1,3步,但同样需要我们申请APNs 推送证书,并且上传到极光推送平台。
2. Xcode8配置自动创建App ID/证书/配置文件
- 在Xcode8下,确保已经登录付费苹果开发者帐号。请开启Application Target的Capabilities->Push Notifications选项。
开启远程推送
2.勾选自动管理App ID
/证书
/配置文件
勾选自动管理
3.检查Xcode生产的App ID
/证书
/配置文件
这步配置好了就可以真机运行了。
检查Xcode生产的App ID/证书/配置文件
3. 创建APNs 推送证书
- 登录开发者网站,并点击按钮创建证书
点击按钮创建证书
2.选择开发环境APNs 推送证书
点击右下角按钮创建
创建开发环境APNs 推送证书
3.选择工程的App ID
选择工程的App ID
4.上传证书请求文件,不知道的童鞋可参照开发证书配置
上传证书请求文件
5.点击下载证书,并双击安装到钥匙串.
安装APNs 推送证书
6.打开钥匙串,并参照下图指示,找到对应的APNs 推送证书,并选择右键导出.
钥匙串导出证书
7.设置证书名字,并选择证书存放位置。
设置证书名字
8.设置证书密码,可不填。极光推送支持证书设置密码,但像leanCloud
推送不支持证书设置密码,各位童鞋可按照实际情况来。最后输入电脑开密码,导出证书。
设置证书密码
输入电脑开机密码导出证书
4. 在极光推送后台创建应用,并上传APNs 推送证书
1.登录极光推送平台,切换到控制台,并创建应用。接下来在应用信息中上传开发APNs 推送证书
。生产环境APNs 推送证书
配置类似,不做赘述.
上传开发APNs 推送证书
- 核对应用的
Bundle ID
等信息是否正确.核对Bundle ID 等信息
5. 项目中集成极光推送SDK
- 导入极光推送SDK
jpush-ios-2.1.9.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及以上)
-
AppDelegate.m 配置
导入以下头文件#import "JPUSHService.h" #import <AdSupport/AdSupport.h> #ifdef NSFoundationVersionNumber_iOS_9_x_Max #import <UserNotifications/UserNotifications.h> #endif
并且遵守
<JPUSHRegisterDelegate>
协议@interface AppDelegate ()<JPUSHRegisterDelegate> @end
注册远程推送
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) { //iOS10以上 JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init]; entity.types = UNAuthorizationOptionAlert|UNAuthorizationOptionBadge|UNAuthorizationOptionSound; [JPUSHService registerForRemoteNotificationConfig:entity delegate:self]; }else if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) { //iOS8以上可以添加自定义categories [JPUSHService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil]; } else { //iOS8以下categories 必须为nil [JPUSHService registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert) categories:nil]; } BOOL isProduction = NO;// NO为开发环境,YES为生产环境 //广告标识符 NSString *advertisingId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]; //Required(2.1.5版本的SDK新增的注册方法,改成可上报IDFA,如果没有使用IDFA直接传nil [JPUSHService setupWithOption:launchOptions appKey:@"极光推送AppKey" channel:nil apsForProduction:isProduction advertisingIdentifier:advertisingId]; 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.获取 APNs(通知) 推送内容
iOS 设备收到一条推送(APNs),用户点击推送通知打开应用时,应用程序根据状态不同进行处理需在 AppDelegate 中的以下方法中添加代码以获取apn内容
1.如果 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.基于iOS 7 及以上的系统版本,如果是使用 iOS 7 的 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
-(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三种类型可以设置
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
7. 极光推送后台发送远程推送测试
1.登录极光推送
,切换到控制台,并点击对应的应用,点击推送按钮
点击推送按钮
点击发送通知
2.设置推送内容
设置推送内容
选择推送环境iOS开发环境,目标人群,发送时间。再点击可选设置设置消息的具体内容。
屏幕快照
3.设置消息具体内容。远程推送分为普通推送/后台推送/静默推送3种类型,并且类型由推送消息设置来决定。关于如何设置请参考iOS 推送全解析,你不可不知的所有 Tips!
屏幕快照 2016-09-26 上午10.54.59.png
4.iOS设备接收到远程推送
接收到远程推送
5.推送历史可以在这里看得到,但有延迟,可能远程推送已接收到,推送历史数据还没有更新到最新。
屏幕快照 2016-09-28 上午10.23.16.png
关于Xcode8下集成极光远程推送的简单介绍,到这里就结束了。
文/赵先生Try(简书作者)
原文链接:http://www.jianshu.com/p/53e0244e6081
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
来源:oschina
链接:https://my.oschina.net/u/2524932/blog/776356