- (3)、为
(2)
中创建的App ID 配置推送 开发证书(测试证书)与推送发布证书
提示:推送发布的证书也一样:点击 Create Certificate
->选择 CSR 文件->下载发布推送证书
(4)、配置描述文件
- iOS证书分2种,1种是开发证书,用来给你(开发人员)做真机测试的;1种是发布证书,发布证书又分发布到app store的(这里不提及)和发布测试的ad hoc证书。
在此我们仅仅创建 iOS App Development
来进行测试远程推送
- 提示:描述文件下载完后记得双击运行一下
- 3.6、获取远程推送要用的
DeviceToken
- (1)、工程的
Bundle identifier
要与我们上面设置的App ID
保持一致,并且打开下面的选项
- (2)、在苹果的APNs服务器注册,以获取DeviceToken
- 通常在
AppDelegate
里面的didFinishLaunchingWithOptions
中添加如下代码进行注册
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([UIDevice currentDevice].systemVersion.doubleValue <= 8.0) { /** 向服务器发请求,要注册推送功能,以此获取到服务器返回的deviceToken type 用来说明 支持的通知形式 如 横幅 声音 角标 */ [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert]; }else{ if (@available(iOS 10.0, *)) { //iOS10 // 1.向用户请求可以给用户推送消息 UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) { }]; }else{ // 1.向用户请求可以给用户推送消息 UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil]; [application registerUserNotificationSettings:notificationSettings]; } // 2.注册远程通知(拿到用户的DeviceToken) [application registerForRemoteNotifications]; } return YES; }
- 注册之后在另外一个代理方法中,拿到DeviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // 将用户的用户名和deviceToken发送给服务器,让服务器进行保存备份即可 NSLog(@"%@", deviceToken); // 例如:<f52a0bc4 57274b41 04684820 f2da2e60 96dd0f8c f24e15b7 7592a8ee b48f5138> // 其中我们服务器要保存的 deviceToken 是不包括两边的尖括号的 } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"%@", error.userInfo); }
- 提示:
- 获取到的
deviceToken
发送给服务器,让服务器进行保存备份即可- 我们服务器要保存的 deviceToken 是不包括两边的尖括号的
- 3.7、测试方式一: 远程通知
- (1)、使用一个第三方的Mac程序来测试:PushMeBaby,并删除里面的资源,把我们自己推送的开发证书与发布证书模仿其命名改名并拖进去
- (2)、修改 PushMeBaby里面的
ApplicationDelegate.m
,把self.deviceToken
修改为我们上面3.6
中运行后拿到的DeviceToken
,切记DeviceToken
不包含左右尖括号
(3)、做完面操作,运行PushMeBaby
,选择相应的内容
3.8、测试方式二:使用SmartPush可以在电脑上方便的模拟APNs推送。运行程序,选择我们生成的证书和填上打印栏获得的DeviceToken,就能在我们的App中看到APNs推送来的带有3DTouch功能的通知。
提示:推送的效果和上面的一样,但是体验更好,建议测试使用 SmartPush
- 3.9、监听远程通知的点击事件,其实和本地通知的监听是一样的,一种是在前台和后台的监听,一种是在app杀死情况下的监听,代码如下
#import "AppDelegate.h" #import <UserNotifications/UserNotifications.h> @interface AppDelegate ()<UNUserNotificationCenterDelegate> @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([UIDevice currentDevice].systemVersion.doubleValue <= 8.0) { //向服务器发请求,要注册推送功能,以此获取到服务器返回的deviceToken //type 用来说明 支持的通知形式 //如 横幅 声音 角标 [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert]; }else{ if (@available(iOS 10.0, *)) { //iOS10 // 1.向用户请求可以给用户推送消息 UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) { }]; }else{ // 1.向用户请求可以给用户推送消息 UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil]; [application registerUserNotificationSettings:notificationSettings]; } // 2.注册远程通知(拿到用户的DeviceToken) [application registerForRemoteNotifications]; } // 判断是否是通过点击通知打开了应用程序 if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) { // 远程通知的监听 } return YES; } - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // 将用户的用户名和deviceToken发送给服务器,让服务器进行保存备份即可 NSLog(@"%@", deviceToken); } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"%@", error); } #pragma mark 用户在后台状态或者前台状态收到远程通知的方法 -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{ NSLog(@"收到远程通知"); // 应用在前台时,也会收到该通知,这时不应该进行页面的跳转 /** UIApplicationStateActive, 前台 UIApplicationStateInactive, 进入前台 UIApplicationStateBackground 在后台 */ if (application.applicationState == UIApplicationStateActive) return; // 前台情况下 不做操作 // 进行页面的跳转 } @end
提示:我们可以使用新的监听用户点击远程通知的方法,如下:(包含上面的两种监听方式)
/* 此方法是新的用于响应远程推送通知的方法 1.如果应用程序在后台,则通知到,点击查看,该方法自动执行 2.如果应用程序在前台,则通知到,该方法自动执行 3.如果应用程序被关闭,则通知到,点击查看,先执行didFinish方法,再执行该方法 4.可以开启后台刷新数据的功能 step1:点击target-->Capabilities-->Background Modes-->Remote Notification勾上 step2:在给APNs服务器发送的要推送的信息中,添加一组字符串如: {"aps":{"content-available":"999","alert":"bbbbb.","badge":1}} 其中content-availabel就是为了配合后台刷新而添加的内容,999可以随意定义 */ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // 前台情况下 不做操作 if (application.applicationState == UIApplicationStateActive) return; //NewData就是使用新的数据 更新界面,响应点击通知这个动作 completionHandler(UIBackgroundFetchResultNewData); }
- 其中
content-availabel
就是为了配合后台刷新而添加的内容,999可以随意定义
四、极光推送 的使用,demo
- 4.1、极光推送 iOS 文档
- APNs 通知:是指通过向 Apple APNs 服务器发送通知,到达 iOS 设备,由 iOS 系统提供展现的推送。用户可以通过 IOS 系统的 “设置” >> “通知” 进行设置,开启或者关闭某一个 App 的推送能力。
- JPush iOS SDK 不负责 APNs 通知的展现,只是向 JPush 服务器端上传 Device Token 信息,JPush 服务器端代理开发者向 Apple APNs 推送通知。
- APNs 通知与应用内消息对比
APNS | 应用内消息 | - |
推送原则 | 由 JPush 服务器发送至 APNS 服务器,再下发到手机。 | 由 JPush 直接下发,每次推送都会尝试发送,如果用户在线则立即收到。否则保存为离线。 |
离线消息 | 离线消息由 APNS 服务器缓存按照 Apple 的逻辑处理。 | 用户不在线 JPush server 会保存离线消息,时长默认保留一天。离线消息保留 5 条。 |
推送与证书环境 | 应用证书和推送指定的 iOS 环境匹配才可以收到。 | 自定义消息与 APNS 证书环境无关。 |
接收方式 | 应用退出,后台以及打开状态都能收到 APNS。 | 需要应用打开,与 JPush 建立连接才能收到。 |
展示效果 | 如果应用后台或退出,会有系统的 APNS 提醒。如果应用处于打开状态,则不展示,iOS 10 开始可实现前台展示。 | 非 APNS,默认不展示。可通过获取接口自行编码处理。 |
处理函数 | Apple 提供的接口:didReceiveRemoteNotification | JPush 提供的接口:networkDidReceiveMessage |
- JPush APNs 通知的意义
- OS 平台上推送通知,只有 APNs 这个官方的通道,是可以随时送达的。一般开发者都是自己部署应用服务器向 APNs Server 推送。
- JPush iOS 推送相比直接向 APNs 推送有什么好处呢?
- 减少开发及维护成本:
- 应用开发者不需要去开发维护自己的推送服务器与 APNs 对接。
- 集成了 JPush iOS SDK 后不必自己维护更新 device token。
- 通过 JPush 的 Web Portal 直接推送,也可以调用 JPush 的 HTTP 协议 API 来完成,开发工作量大大减少。
- 减少运营成本:
- 极光推送支持一次推送,同时向 Android, iOS, WinPhone 三个平台。支持统一的 API 与推送界面。
- 极光推送提供标签、别名绑定机制,以及提供了非常细分的用户分群方式,运营起来非常简单、直观。
- 提供应用内推送:
- 除了使得 APNs 推送更简单,也另外提供应用内消息推送。这在类似于聊天的场景里很有必要。
- 4.2、在极光推送平台创建一个应用
- 4.3、iOS SDK 集成,官网讲解的很详细,在此我们就简单的采用 Cocoapods 导入 极光推送的iOS SDK
- 通过 Cocoapods 下载地址:
pod 'JPush'
提示:如果无法导入最新版本,请执行
pod repo update master
这个命令来升级本机的 pod 库,然后重新pod 'JPush'
- 如果需要安装指定版本则使用以下方式(以 3.1.0 版本为例):
pod 'JPush', '3.1.0'
提示:导入成功后还有一些工程的配置问题大家看官方文档即可
- 4.4、测试项目的
Bundle Identifier
要与我们上面创建证书的Bundle ID
保持一致,并且打开如下图所示
静默推送(silent_push):如果只携带content-available: 1,不携带任何badge,sound 和消息内容等参数,则可以不打扰用户的情况下进行内容更新等操作即为“Silent Remote Notifications”。
- 4.5、在
AppDelegate.m
导入极光推送的相应代码,在此我就不再导入了,说一下几个参数,在didFinishLaunchingWithOptions
方法里面会使用到下面的参数
- appKey:选择 Web Portal 上 的应用 ,点击“设置”获取其 appkey 值。请确保应用内配置的 appkey 与 Portal 上创建应用后生成的 appkey 一致。
提示其实也就是我们上面创建应用成功后生成的key
- channel:指明应用程序包的下载渠道,为方便分渠道统计,具体值由你自行定义,如:App Store。
- apsForProduction:1.3.1 版本新增,用于标识当前应用所使用的 APNs 证书环境。
- 0(默认值)表示采用的是开发证书,1 表示采用生产证书发布应用。
注:此字段的值要与 Build Settings的Code Signing 配置的证书环境一致。
- advertisingIdentifier: 详见关于 IDFA。
- 在demo里面我们写了一个来处理推送是跳转还是其他操作的方法
#pragma mark 对于推送的处理(可以把上面notificationUI的方法替换掉) - (void)goToMessageViewControllerWithDic:(NSDictionary *)userInfo { if ([[userInfo objectForKey:@"go"] isEqualToString:@"update"]) { // 应用程序更新 [[UIApplication sharedApplication]openURL:[NSURL URLWithString:@""]]; return; } //将字段存入本地,因为要在你要跳转的页面用它来判断,这里我只介绍跳转一个页面, NSUserDefaults *pushJudge = [NSUserDefaults standardUserDefaults]; [pushJudge setObject:@"push"forKey:@"push"]; [pushJudge synchronize]; // 这个是我要跳到的测试页面 (你的目标页面) TestViewController *testVC = [[TestViewController alloc]init]; UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:testVC];//这里加导航栏是因为我跳转的页面带导航栏,如果跳转的页面不带导航,那这句话请省去。 [self.window.rootViewController presentViewController:nav animated:YES completion:nil]; }
- 4.6、在极光推送后台进行推送,发送通知
在当我们点击推送后,我们在手机可以收到如下效果
在app的 AppDelegate.m 打印推送的内容,如下
到此,极光推送使用完毕,有兴趣还可以看看 个推 的推送