====== 消息推送详解 ======
本文主要介绍了使用云之讯 IM 时,如何使用远程推送、何时会收到远程推送、如何获取远程推送的内容。\\
=====一、何时会收到远程推送 =====
==== 1、iOS APP应用状态 ====
在讲解云之讯IM离线推送的机制之前,我们先来了解iOS APP的生命周期和状态。 iOS应用程序的生命周期,应用程序各个状态的变换,这些对于开发者来说都是很重要的。 iOS系统的资源是有限的,应用程序在前台和在后台的状态是不一样的。在后台时,程序会受到系统的很多限制,这样可以提高电池的使用和用户体验。\\
iOS应用的各个状态如下:\\
*1、**Not running 未运行** 程序没启动\\
*2、**Inactive 未激活** 程序在前台运行,不过没有接收到事件。在没有事件处理情况下程序通常停留在这个状态\\
*3、**Active 激活** 程序在前台运行而且接收到了事件。这也是前台的一个正常的模式\\
*4、**Backgroud 后台** 程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态\\
*5、**Suspended 挂起** 程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存\\
下图是程序状态的变化图:\\
{{ :iosapp状态.png?nolink& }}\\
当应用程序处于挂起和未运行状态时,程序和云之讯服务器的交互是断开的。
在这段时间内,如果您已经设置好了离线推送,云之讯服务器将使用离线推送功能将消息推送到您的用户设备上。
如果您还未设置离线推送,下面的教程将手把手教您实现离线推送功能。
====2、云之讯SDK运行状态 ====
云之讯SDK 根据 iOS App 运行的运行状态特性,主要有以下三种运行状态:\\
*1、**前台状态** 如字面意思,App 前台可见时 SDK 处于前台状态。此时 App 使用云之讯的 socket 来收发消息.\\
*2、**后台活动状态** 当 App 进入后台三分钟之内,SDK 处于后台活跃状态。此时 App 使用云之讯的 socket 接收消息。在后台活动状态下收到消息, SDK 不会弹出本地通知,如果您需要可以自己弹出本地通知提示。\\
*3、 **后台挂起状态** 当 App 进入后台三分钟之后或被杀进程或被冻结(取决于系统的内存情况),SDK 将处于后台挂起状态。此时云之讯的 socket 会断开,云之讯后台服务会通过 APNs 将消息以远程推送的形式下发到客户端。 此状态下如果有人给该用户发送消息,云之讯的服务器会根据 DeviceToken 和推送证书将消息发送到苹果推送服务器,苹果服务器会将该消息推送到客户端。\\
由于本地通知和远程推送表现形式类似,不易区分,您在调试时可以通过杀进程来测试远程推送,App 刚进入后台测试本地通知。
当 SDK 处于后台挂起状态或未启动状态时,App 会收到远程推送。
====3、离线推送流程 ====
当 SDK 处于后台挂起状态或未启动状态时,并且已经上传了 DeviceToken ,这时候如果有人给该用户发送消息,云之讯的服务器会根据 DeviceToken 和推送证书将消息发送到苹果推送服务器(APNs)。 苹果推送服务器会根据 DeviceToken 查找相应的设备,并根据推送证书中的 BundleID 和 App 打包时使用的 Provisioning Profile 查找 App,从而确定唯一的设备上的唯一 App,并进行远程推送。\\
====4、开发环境和生产环境 ====
苹果推送服务器区分开发环境(Development)和生产环境(Production),两个环境的服务器不同,使用的 P12 证书不同,完全隔离。
有几点需要注意的。
DeviceToken 是唯一标识客户端的凭证,所以必须上传云之讯服务器才能使用远程推送。
模拟器收不到远程推送。
越狱的设备 APNs 服务不能保证,所以不一定能收到远程推送。
APNs 使用 BundleID 区分 App,使用通配符 BundleID 的 App 将无法使用远程推送。
=====二、如何设置远程推送 =====
====1、为您的App开启远程推送服务 ====
您需要为您的APP制作一个包含Push Notification服务的APP ID。\\
登陆[[https://developer.apple.com/|Apple Developer]] ,进入Identifiers,选择App IDs。
{{ :appid0.png?nolink& }}
{{ :appid2.png?nolink& }}
您可以重新创建一个APP ID,也可以在之前的APP ID的基础上增加push服务。需要注意的是,您 App 的 BundleID 不能使用通配符,否则将无法使用远程推送服务。
{{ :appid3.png?nolink& }}
打开离线推送服务
{{ :appid4.png?nolink& }}
{{ :appid5.png?nolink& }}
====2、制作推送证书 ====
选中您的AppID,选中Edit
{{ :appid6.png?nolink& }}
您可以看见,在Push Notification下方有两个SSL Certificate,分别是开发环境和生成环境的远程推送证书
{{ :appid7.png?nolink& }}
点击 Create Certificate ,这时候会提示您需要一个 Certificate Signing Request(CSR)。
{{ :appid8.png?nolink& }}
根据提示,在您的Mac上打开钥匙串访问,选择【证书助理】【从证书颁发机构请求证书】
{{ :appid9.png?nolink& }}
输入您的邮箱、姓名或者公司名,选择保存到磁盘,点击继续,就会生成*.certSigningRequest的文件
{{ :appid10.png?nolink& }}
{{ :appid11.png?nolink& }}
然后返回 Apple Developer 网站,点击 Continue,上传生成的 *.certSigningRequest 文件,点击 Generate ,即可生成推送证书。
{{ :appid12.png?nolink& }}
{{ :appid13.png?nolink& }}
按照同样的步骤,生成生产环境的推送证书
{{ :appid14.png?nolink& }}
此时,您可以在 Push Notification 下方看见目前每个环境对应的推送证书。
{{ :appid15.png?nolink& }}
将上面的 SSL Certificate 都下载到 Mac 本地,双击打开,系统会将其导入钥匙串中。 打开钥匙串应用,选中对应的证书,右键选择导出。保存 P12 文件时,可以为其设置密码,也可以不设置密码。
{{ :appid17.png?nolink& }}
{{ :appid18.png?nolink& }}
{{ :appid19.png?nolink& }}
{{ :appid20.png?nolink& }}
{{ :appid21.png?nolink& }}
====3、上传证书到云之讯平台 ====
进入云之讯开发者控制台,创建应用。如果您不了解这一步,请前往[[http://docs.ucpaas.com/doku.php?id=%E6%96%B0%E6%89%8B%E6%8C%87%E5%BC%95|云之讯开发者账户指南]]。\\
创建完成后,进入【应用管理】->【应用列表】->【对应的应用】->【IM iOS推送证书设置】,上传刚才到处的推送证书。
{{ :appid22.png?nolink& }}
您上传的 P12 证书必须与环境相匹配。开发环境必须上传 Development 的 Push 证书,生产环境必须上传 Production 的 Push 证书。
{{ :appid23.png?nolink& }}
====4、生成 provisioning profile 文件 ====
Xcode 编译打包的时候,需要使用使用 provisioning profile 来指明 AppID 、证书和设备。\\
而远程推送与证书、设备相关,所以必须正确设置相应环境的 provisioning profile,否则将无法收到远程推送。\\
在 Apple Developer 中,选择 Provisioning Profile,选择生成开发环境或者生产环境的 provisioning profile。\\
{{ :appid24.png?nolink& }}
选择对应的App ID
{{ :appid25.png?nolink& }}
选择允许使用的开发者证书
{{ :appid26.png?nolink& }}
选择允许使用的设备
{{ :appid27.png?nolink& }}
输入名称就可以生成
{{ :appid28.png?nolink& }}
{{ :appid29.png?nolink& }}
如果您的 App 是 App-Store 类型的,但是还没有在 App Store 上架,在上架之前如果您想使用生产环境测试远程推送,您需要生成一个 Ad-Hoc 的 Provisioning Profile ,并在 Xcode 中使用其进行打包,导出为 Ad Hoc Deployment。
{{ :appid30.png?nolink& }}
====5、在代码中请求远程推送权限 ====
向用户请求允许推送
/**
* 注册推送
*/
UIApplication *application = [UIApplication sharedApplication];
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
//注册推送, 用于iOS8以及iOS8之后的系统
UIUserNotificationSettings *settings = [UIUserNotificationSettings
settingsForTypes:(UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert)
categories:nil];
[application registerUserNotificationSettings:settings];
} else {
//注册推送,用于iOS8之前的系统
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
/**
* 注册用户通知设置
*/
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
[application registerForRemoteNotifications];
}
您需要通过TCPSDK中UCSTcpClient的单例,调用-setPushEnvironment:deviceToken:方法设置推送环境和设备号DeviceToken。
/**
* 设置离线推送的环境和设备号DeviceToke。如果需要使用推送离线推送,则必须调用此方法。
* @param environment 离线推送的环境.具体见UCSPushEnvironment,不设置的话,默认是开发环境。
* @param deviceToken 从系统获取到的设备号DeviceToken。
*/
- (void)setPushEnvironment:(UCSPushEnvironment)environment
deviceToken:(NSData *)deviceToken;
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
// 设置推送环境和token
[[UCSTcpClient sharedTcpClientManager] setPushEnvironment:UCSPushEnvironment_Production deviceToken:deviceToken];
}
DeviceToken 是系统提供的,从苹果服务器获取的,用于 APNs 远程推送必须使用的设备唯一值。
您需要将-didRegisterForRemoteNotificationsWithDeviceToken: 获取到的 DeviceToken,传给 SDK。
SDK 会将此DeviceToken保存,在 Connect 时会自动上传到云之讯服务器,并与用户ID绑定,用于远程推送。
==== 6、用户允许推送 ====
以上步骤都已经实现后,还需要使用您App的用户允许通知,才能收到远程推送。您可以在设备的设置应用中,查看当前App是否允许通知。