用户工具

消息推送详解

这是本文档旧的修订版!


消息推送详解

本文主要介绍了使用云之讯 IM 时,如何使用远程推送、何时会收到远程推送、如何获取远程推送的内容。

一、何时会收到远程推送

1、iOS APP应用状态

在讲解云之讯IM离线推送的机制之前,我们先来了解iOS APP的生命周期和状态。 iOS应用程序的生命周期,应用程序各个状态的变换,这些对于开发者来说都是很重要的。 iOS系统的资源是有限的,应用程序在前台和在后台的状态是不一样的。在后台时,程序会受到系统的很多限制,这样可以提高电池的使用和用户体验。
iOS应用的各个状态如下:

  • 1、Not running 未运行 程序没启动
  • 2、Inactive 未激活 程序在前台运行,不过没有接收到事件。在没有事件处理情况下程序通常停留在这个状态
  • 3、Active 激活 程序在前台运行而且接收到了事件。这也是前台的一个正常的模式
  • 4、Backgroud 后台 程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态
  • 5、Suspended 挂起 程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存

下图是程序状态的变化图:

当应用程序处于挂起和未运行状态时,程序和云之讯服务器的交互是断开的。
在这段时间内,如果您已经设置好了离线推送,云之讯服务器将使用离线推送功能将消息推送到您的用户设备上。
如果您还未设置离线推送,下面的教程将手把手教您实现离线推送功能。

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。
登陆Apple Developer ,进入Identifiers,选择App IDs。

您可以重新创建一个APP ID,也可以在之前的APP ID的基础上增加push服务。需要注意的是,您 App 的 BundleID 不能使用通配符,否则将无法使用远程推送服务。

打开离线推送服务

2、制作推送证书

选中您的AppID,选中Edit

您可以看见,在Push Notification下方有两个SSL Certificate,分别是开发环境和生成环境的远程推送证书

点击 Create Certificate ,这时候会提示您需要一个 Certificate Signing Request(CSR)。

根据提示,在您的Mac上打开钥匙串访问,选择【证书助理】【从证书颁发机构请求证书】

输入您的邮箱、姓名或者公司名,选择保存到磁盘,点击继续,就会生成*.certSigningRequest的文件

然后返回 Apple Developer 网站,点击 Continue,上传生成的 *.certSigningRequest 文件,点击 Generate ,即可生成推送证书。

按照同样的步骤,生成生产环境的推送证书

此时,您可以在 Push Notification 下方看见目前每个环境对应的推送证书。

将上面的 SSL Certificate 都下载到 Mac 本地,双击打开,系统会将其导入钥匙串中。 打开钥匙串应用,选中对应的证书,右键选择导出。保存 P12 文件时,可以为其设置密码,也可以不设置密码。

3、上传证书到云之讯平台

进入云之讯开发者控制台,创建应用。如果您不了解这一步,请前往云之讯开发者账户指南
创建完成后,进入【应用管理】→【应用列表】→【对应的应用】→【IM iOS推送证书设置】,上传刚才到处的推送证书。

您上传的 P12 证书必须与环境相匹配。开发环境必须上传 Development 的 Push 证书,生产环境必须上传 Production 的 Push 证书。

4、生成 provisioning profile 文件

Xcode 编译打包的时候,需要使用使用 provisioning profile 来指明 AppID 、证书和设备。
而远程推送与证书、设备相关,所以必须正确设置相应环境的 provisioning profile,否则将无法收到远程推送。
在 Apple Developer 中,选择 Provisioning Profile,选择生成开发环境或者生产环境的 provisioning profile。

选择对应的App ID

选择允许使用的开发者证书

选择允许使用的设备

输入名称就可以生成

如果您的 App 是 App-Store 类型的,但是还没有在 App Store 上架,在上架之前如果您想使用生产环境测试远程推送,您需要生成一个 Ad-Hoc 的 Provisioning Profile ,并在 Xcode 中使用其进行打包,导出为 Ad Hoc Deployment。

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是否允许通知。


页面工具