iOS 推送设置

更新时间:2022-02-28

APNs 是苹果官方提供的推送解决方案,主要用于在 app 处于不活跃状态时向设备发送实时通知。使用环信即时通讯 IM SDK 时,当消息接收方不在线,环信即时通讯 IM 的服务器会通过苹果的 APNs 服务向接收方设备发消息推送,该服务器会暂时保存这些消息,等用户再次上线时通过环信即时通讯 IM 的长连接投递。同时开发者可根据需要设置推送的显示样式,免打扰时间段等。

比如:当你的 app 处于不活跃状态时,有用户向你发送了消息,此时你的手机的通知中心会弹出消息相关的通知,当你再次打开 app 并登录成功,环信即时通讯 IM SDK 会主动拉取你不在线时的消息。

你不需要单独处理和消息相关的 APNs,通过 APNs 收到的只是消息通知,等用户账号登录成功后才会把消息从服务器拉过来。这里角标表示的是离线消息数,并不是实际的未读消息数。

 推送

使用消息推送前,需要在你的设备开启推送权限,并将推送证书上传到 环信即时通讯 IM 管理后台。

1. 生成 CSR 文件

生成 Certificate Signing Request(CSR):

填写你的邮箱(这个邮箱是申请 App ID 的付费帐号)和常用名称(一般默认是计算机名,不用更改),并选择保存到硬盘:

点击继续:

在本地生成了名为 EMImDemoAPS.certSigningRequest 的 CSR 文件 。

2. 创建 App ID

生成 App ID ,如果已经有 App ID 可以跳至第3步。

选择 App ID,点击 Continue

选择 App, 点击 Continue

输入你的 App ID 描述信息,可以输入工程名;Bunble ID(在工程的 General 信息中),一般格式为 com.youcompany.youprojname。

选择需要支持 Push Notification,点击 Continue;

确定信息无误,点击 Register;

3. 创建 app 的 APS 证书

回到 App IDs 选择你需要推送的 app。

找到 Push Notifications, 点击 Configure

如果是开发模式,点击 Development SSL Certificate 下的 Create Certificate。如果是生产模式,点击 Production SSL Certificate 下的 Create Certificate

Platform 选择 iOS , Choose File 选择第一步中创建的 CSR 文件,点击 Continue

aps 文件创建成功了,点击 Download 下载到本地。(文件名:开发版本为 aps_development.cer,发布版本为 aps.cer):

4. 生成 Push 证书

导入证书

双击上一节下载的文件(aps_development.ceraps.cer)将其安装到电脑,在“钥匙串访问”中,可以看到已经导入的证书。

右键选择导出为 p12 文件, (例:存储为 EMImDemoAPS.p12):

5. 生成 Provisioning Profile 文件(PP 文件)

选择 iOS App Development(这里演示开发版描述文件的创建, 发布版本的创建流程一样,如果发布版本,请选择 App Store),点击 Continue。

App ID 选择需要创建 PP 文件的 App ID, 点击 Continue

选择需要加入开发的设备,只有加入了的设备才能进行真机调试,创建发布版本时没有这个步骤,点击 Continue

输入 PP 文件的名称,点击 Generate

PP 文件生成完成, 点击 Download

6. 上传到环信即时通讯 IM 管理后台

 图

 图

 图

1. 在 app 中开启推送权限

需要在 xcode 中为 app 开启推送权限。 Targets → Capability → Push Notifications

2. 将证书名称传递给 SDK

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // 注册推送。
  [application registerForRemoteNotifications];

  // 初始化 `Options`,设置 App Key。
  EMOptions *options = [EMOptions optionsWithAppkey:@"easemob-demo#easeim"];

  // 填写上传证书时设置的名称。
  options.apnsCertName = @"PushCertName";

  [EMClient.sharedClient initializeSDKWithOptions:options];

  return YES;
  }
  

3. 获取并将 device token 传递给 SDK

DeviceToken 注册后,iOS 系统会通过以下方式将 DeviceToken 回调给你,你需要把 DeviceToken 传给 SDK。

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [EMClient.sharedClient registerForRemoteNotificationsWithDeviceToken:deviceToken completion:^(EMError *aError) {
      if (aError) {
          NSLog(@"bind deviceToken error: %@", aError.errorDescription);
      }
  }];
  }
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  NSLog(@"Register Remote Notifications Failed");
  }
  

4. 配置推送功能

主要是指在推送时显示的一些内容,包括推送显示的名称,推送的样式,群组是否接收推送以及推送免打扰时间等。

4.1 设置推送显示名称

设置推送显示名称用于推送通知时显示发送方的名称。

[EMClient.sharedClient.pushManager updatePushDisplayName:@"displayName" completion:^(NSString * aDisplayName, EMError * aError) {
    if (aError) 
    {
        NSLog(@"update push display name error: %@", aError.errorDescription);
    }
}];

4.2 设置推送显示样式

推送显示样式主要适用于是否显示消息内容详情。

[EMClient.sharedClient.pushManager updatePushDisplayStyle:EMPushDisplayStyleSimpleBanner completion:^(EMError * aError)
{
    if(aError)
    {
        NSLog(@"update display style error --- %@", aError.errorDescription);
    }
}];

DisplayStyle 是枚举类型。

参数 描述
EMPushDisplayStyleSimpleBanner 显示”你有一条新消息”。
EMPushDisplayStyleMessageSummary显示消息内容。

4.3 设置群组免打扰

群组免打扰指不接收一些群组的推送。群组免打扰模式下,用户与服务器断开连接后不会再收到群的推送。

[EMClient.sharedClient.pushManager updatePushServiceForGroups:groupIds disablePush:YES completion:^(EMError * aError)
{
    if(aError)
    {
        NSLog(@"update groups disable push error --- %@", aError.errorDescription);
    }
}];

groupIds 群组 ID 列表。

4.4 获取免打扰群组列表

NSArray<NSString*>* groupIds = [EMClient.sharedClient.pushManager noPushGroups];

groupIds 当前内存中保存的不接收推送的群组 ID。如果需要取服务器数据,需要先调用: 获取推送属性

4.5 设置单人免打扰

[EMClient.sharedClient.pushManager updatePushServiceForUsers:userIds disablePush:YES completion:^(EMError * _Nonnull aError) {
    if(aError)
    {
        NSLog(@"update users disable push error --- %@", aError.errorDescription);
    }
}];

userIds 用户 ID 列表。

4.6 获取单人免打扰列表

NSArray<NSString*>* userIds = [EMClient.sharedClient.pushManager noPushUIds];

userIds 当前内存中保存的不接收推送的 ID,如果需要取服务器数据,需要先调用: 获取推送属性

4.7 设置免打扰时间

对于单聊和群聊,可设置免打扰时间段。在设置的时间段内不再有推送通知。

设置不推送的时间段

该方法为同步方法。

EMError *aError = [EMClient.sharedClient.pushManager disableOfflinePushStart:22 end:7];
if (aError) 
{
    NSLog(@"disable push error --- %@", aError.errorDescription);
}
参数 描述
start范围是 0 到 24 的整数。
end 范围是 0 到 24 的整数。

如:start22end7,则表示晚 10 点到早 7 点不接收推送。

开启接收推送

该方法为同步方法。

EMError *aError = [EMClient.sharedClient.pushManager enableOfflinePush];
if (aError) 
{
    NSLog(@"enable push error --- %@", aError.errorDescription);
}

4.8 获取推送属性

从服务获取当前与推送相关的配置信息。

[EMClient.sharedClient.pushManager getPushNotificationOptionsFromServerWithCompletion:^(EMPushOptions * aOptions, EMError * aError)
{
    if (aError)
    {
        NSLog(@"get push options error --- %@", aError.errorDescription);
    }
}];

EMPushOptions推送配置对象。

属性名 描述
displayName 对方收到推送时发送方展示的名称。
displayStyle 推送显示类型。
noDisturbingStartH不接收推送的开始时间。
noDisturbingEndH 不接收推送的结束时间。
isNoDisturbEnable 是否开启了不接收推送。只要设置了免打扰时间,任何时间段均返回 YES。

5. 解析收到的推送字段

当设备收到推送并点击时,iOS 会通过 launchOptions 将推送中的 JSON 传递给 app,这样就可以根据推送的内容定制 app 的一些行为,比如页面跳转等。 当收到推送通知并点击推送时,app 获取推送内容的方法:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      NSDictionary *userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
  }
  

userInfo:

{
    "aps":{
        "alert":{
            "body":"你有一条新消息"
        },   
        "badge":1,               
        "sound":"default"   
    },
    "f":"6001",                  
    "t":"6006", 
    "g":"1421300621769",    
    "m":"373360335316321408"
}
参数 描述
body 显示内容。
badge角标数。
sound提示铃声。
f 消息发送方 ID。
t 消息接收方 ID。
g 群组 ID,单聊无该字段。
m 消息 ID。

自定义字段

向推送中添加自定义业务字段满足业务需求,例如,通过这条推送跳转到某个活动页面。

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"test"];
EMChatMessage *message = [[EMChatMessage alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_apns_ext":@{@"extern":@"custom string"}}; 
message.chatType = EMChatTypeChat; 
[EMClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 描述
body 消息体。
ConversationID消息属于的会话 ID。
from 消息发送方,一般为当前登录 ID。
to 消息接收方 ID,一般与 ConversationID 一致。
em_apns_ext 消息扩展,使用扩展的方式向推送中添加自定义字段,该值为固定值,不可修改。
extern 自定义字段 key,用于设置自定义的内容,该值为固定值,不可修改。
custom string 自定义字段内容。

解析的内容

{
    "apns": {
        "alert": {
            "body": "test"
        }, 
        "badge": 1, 
        "sound": "default"
    }, 
    "e": "custom string", 
    "f": "6001", 
    "t": "6006", 
    "m": "373360335316321408"
}
参数 描述
body 显示内容。
badge角标数。
sound提示铃声。
f 消息发送方 ID。
t 消息接收方 ID。
e 自定义信息。
m 消息 ID。

自定义显示

自定义显示内容时,你可以随意设置 APNs 通知时显示的内容。

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"test"];
EMChatMessage *message = [[EMChatMessage alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_apns_ext":@{@"em_push_content":@"custom push content"}}; 
message.chatType = EMChatTypeChat; 
[EMClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 描述
body 消息体。
ConversationID 消息属于的会话 ID。
from 消息发送方,一般为当前登录 ID。
to 消息接收方 ID,一般与 ConversationID 一致。
em_apns_ext 消息扩展,使用扩展的方式向推送中添加自定义字段,该值为固定值,不可修改。
em_push_content 自定义字段,用于设置自定义要显示的内容,该值为固定值,不可修改。
custom push content自定义显示的内容。

解析的内容

{
    "aps":{
        "alert":{
            "body":"custom push content"
        },   
        "badge":1,               
        "sound":"default"        
    },
    "f":"6001",                  
    "t":"6006",                  
    "m":"373360335316321408",
}
参数 描述
body 显示内容。
badge角标数。
sound提示铃声。
f 消息发送方 ID。
t 消息接收方 ID。
m 消息 ID。

自定义铃声

推送铃声是指用户收到推送时的提示音,你需要将音频文件加入到 app 中,并在推送中配置使用的音频文件名称。 - 支持格式 Linear PCM MA4 (IMA/ADPCM) µLaw aLaw。 - 音频文件存放路径 AppData/Library/Sounds,时长不得超过 30 秒。

更多内容可以参考苹果官方文档Generating a Remote Notification.

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"test"];
EMChatMessage *message = [[EMChatMessage alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_apns_ext":@{@"em_push_sound":@"custom.caf"}};
message.chatType = EMChatTypeChat; 
[EMClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 描述
body 消息体。
ConversationID消息属于的会话 ID。
from 消息发送方,一般为当前登录 ID。
to 消息接收方 ID,一般与 ConversationID 一致。
em_apns_ext 消息扩展,使用扩展的方式向推送中添加自定义字段,该值为固定值,不可修改。
em_push_sound 自定义字段,用于设置自定义要显示的内容,该值为固定值,不可修改。
custom.caf 音频文件名称。

解析的内容

{
    "aps":{
        "alert":{
            "body":"你有一条新消息"
        },  
        "badge":1,  
        "sound":"custom.caf"  
    },
    "f":"6001",  
    "t":"6006",  
    "m":"373360335316321408"  
}
参数 描述
body 显示内容。
badge角标数。
sound提示铃声。
f 消息发送方 ID。
t 消息接收方 ID。
m 消息 ID。

强制推送

使用该方式设置后,本条消息会忽略接收方的免打扰设置,不论是否处于免打扰时间段都会正常向对方推送通知;

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"test"];
EMChatMessage *message = [[EMChatMessage alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_force_notification":@YES};
message.chatType = EMChatTypeChat; 
[EMClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 描述
body 消息体。
ConversationID 消息属于的会话 ID。
from 消息发送方,一般为当前登录 ID。
to 消息接收方 ID,一般与 ConversationID 一致。
em_force_notification标志是否为强制推送的关键字,不可修改。

基于 UNNotificationServiceExtension 的扩展功能

在 iOS10 之后生效,目的是为了唤醒 UNNotificationServiceExtension,让你可以做更多的扩展。

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"test"];
EMChatMessage *message = [[EMChatMessage alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_apns_ext":@{@"em_push_mutable_content":@YES}}; 
message.chatType = EMChatTypeChat; 
[EMClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 描述
body 消息体。
ConversationID 消息属于的会话 ID。
from 消息发送方,一般为当前登录 ID。
to 消息接收方 ID,一般与 ConversationID 一致。
em_apns_ext 消息扩展,使用扩展的方式向推送中添加自定义字段,该值为固定值,不可修改。
em_push_mutable_content是否使用推送扩展的关键字,不可修改。

解析的内容

{
    "aps":{
        "alert":{
            "body":"test"
        },  
        "badge":1,  
        "sound":"default",
        "mutable-content":1  
    },
    "f":"6001",  
    "t":"6006",  
    "m":"373360335316321408"  
}
参数 描述
body 显示内容。
badge 角标数。
sound 提示铃声。
mutable-content苹果要求的关键字,存在之后才可唤醒 UNNotificationServiceExtension。
f 消息发送方 ID。
t 消息接收方 ID。
m 消息 ID。