APNs推送

  1. 当App在前台可见的时候,SDK处于前台活跃状态,此时是使用SDK长连接接收消息。
  2. 当App进入后台且在2分钟之内的时候,SDK处于后台活跃状态,此时是使用SDK长连接接收消息(用户根据需要实现本地通知,否则将不会有本地通知提示弹出)。
  3. 当App进入后台超过2分,被系统挂起,此时SDK处于不活跃状态,或者是主动把App进程杀死,此时如果有新消息,是通过苹果的APNs服务进行提醒的。当App再次启动,SDK会去服务器拉取不活跃期间的消息。

由于本地通知和APNs不好区分,调试时建议您将App进程杀死,确保所有的提醒都是来自于APNs推送。

当SDK处于前台或后台活跃状态时:

当SDK处于不活跃状态或App进程被杀死时:

APNs只是起到通知作用,当用户启动App,消息会通过SDK长连接收取到客户端。

申请远程推送证书

首先,登录苹果的开发者中心。 创建App

为App命名,此处bundle id不能用通配符,否则无法收到推送。

打开推送功能

创建推送证书

如果您是测试开发环境,选择development下的Apple Push Notification service SSL(如果是生产,则需要选择Production下的)

选择证书所属的App

上传CSR文件

下面,我们来创建一个CSR文件,首先,选择“钥匙串访问”

钥匙串访问 – 证书助理 – 从证书颁发机构请求证书

电子邮件没有要求,符合邮件格式就可以,常用名也没有限制,要注意将“请求是”的参数改为“存储到磁盘”, 之后会得到一个CSR文件。

返回到“上传CRS文件”页面,将刚刚生成的CSR文件上传。

点击继续,会得到一个下载页面。

点击下载,就会下载一个aps_development.cer。(production的是aps.cer)

双击下载的cer文件,就会将它添加到“钥匙串访问”中。查看证书,会看到一个以bundle id 证书,这个就是新添加进去的。

右键导出,注意右键的时候不要展开,就在证书上点击右键

保存

此处需要记住密码,后面需要用到。

允许钥匙串访问此项目。

保存,您将得到一个p12后缀的文件。

上传推送证书到环信

登录环信管理后台,找到要上传证书的Appkey,点击进入详情。

选择“推送证书”

选择“iOS”

为证书起名,并记住名称,后续有用。选择上传证书,将上一步中生成的P12文件上传,并设置导出时设置的密码。选择证书类型,此处是“开发环境”(如果之前用的是production,则此处应该选择生产)。填写应用包名,应为bundle id,点击上传,完成上传证书操作。

客户端如何申请DeviceToken

1、 注册远程通知

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];
}

2、 将得到的deviceToken传到SDK

// 将得到的deviceToken传给SDK
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [[EMClient sharedClient] bindDeviceToken:deviceToken];
    });
}

注:必须是真机,模拟器不支持APNs

客户端如何配置推送证书

SDK在初始化的时候,设置要使用的推送证书。

// 设置Appkey
EMOptions *options = [EMOptions optionsWithAppkey:@"easemob-demo#chatdemoui"];
// 设置推送证书名称
options.apnsCertName = @"apnsTest";
// 初始化SDK
[[EMClient sharedClient] initializeSDKWithOptions:options];

如何实现本地通知

本地通知,是在长连接还存在的时候,通过环信收消息的回调接收到消息,之后判断当前App的状态,如果是在后台的情况下,就可以`通过代码主动弹出一个通知`,来起到通知用户的作用。具体参考如下:

- (void)messagesDidReceive:(NSArray *)aMessages {
		for (EMMessage *msg in aMessages) {
	        UIApplicationState state = [[UIApplication sharedApplication] applicationState];
	        // App在后台
	        if (state == UIApplicationStateBackground) {
					//发送本地推送
	   	         if (NSClassFromString(@"UNUserNotificationCenter")) { // ios 10
                // 设置触发时间
                UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.01 repeats:NO];
                UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
                content.sound = [UNNotificationSound defaultSound];
                // 提醒,可以根据需要进行弹出,比如显示消息详情,或者是显示“您有一条新消息”
                content.body = @"提醒内容";
                UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:msg.messageId content:content trigger:trigger];
                [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];
            }else {
                UILocalNotification *notification = [[UILocalNotification alloc] init];
                notification.fireDate = [NSDate date]; //触发通知的时间
                notification.alertBody = @"提醒内容";
                notification.alertAction = @"Open";
                notification.timeZone = [NSTimeZone defaultTimeZone];
                notification.soundName = UILocalNotificationDefaultSoundName;
                [[UIApplication sharedApplication] scheduleLocalNotification:notification];
            }
        }
    }
}

推送内容解析

在环信中,APNs是在长连接不存在的时候,才会产生(即App进程不存在或者被挂起)。此时iOS是不允许直接得到APNs内容的,但是当用户点击推送的提示栏,此时是可以在

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

的launchOptions中得到APNs的内容。具体解析结构如下:

{
    "aps":{
        "alert":{
            "body":"您有一条新消息" // 消息内容
        },	 
        "badge":1,	// 角标数
        "sound":"default"	// 提示音	 
     },
    "f":"6001",	// 消息发送方
    "t":"6006",	// 消息接收方	 
    "m":"373360335316321408", // 消息id
    "g":"1421300621769"  // 群组id(如果是单聊则没有该字段)
 }

更多用法,可以参考 (APNs解析

证书到期后如何更新

证书到期后,要更换新的推送证书,需要在环信管理后台将旧的删除,之后重新上传,上传时的命名要与旧证书的命名一致

一个Appkey下是否可以传多组推送证书

一个appkey下可以传多个证书,这就可以实现夸App聊天,在不同App中初始化sdk的时候,指定不同的推送证书,每个证书对应当前App的bundle id,这样,用户在登录不同的App的时候就会绑定到不同的推送证书,从而实现夸App的聊天和推送。