====== 消息推送详解 ====== 本文主要介绍了使用云之讯 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是否允许通知。