即时通讯 IM 支持集成 APNs 消息推送服务,为 iOS 开发者提供低延时、高送达、高并发、不侵犯用户个人数据的离线消息推送服务。
当客户端应用进程被关闭等原因导致用户离线,即时通讯 IM 会通过 APNs 消息推送服务向该离线用户的设备推送消息通知。当用户再次上线时,会收到离线期间所有消息。
下图展示了消息推送的基本工作流程:
消息推送流程如下:
开发者通过声网控制台配置 App 的推送证书,需填写证书名称及推送密钥等信息。该步骤须在登录即时通讯 IM SDK 成功后进行。
证书名称是声网即时通讯服务器用于判断目标设备使用哪种推送通道的唯一条件,因此必须确保与 iOS 终端设备上传的证书名称一致。
参考以下步骤开启 APNs 推送服务:
CertificateSigningRequest.certSigningRequest
。App ID
,点击 Continue
。com.YourCompany.YourProjectName
。Register
。.p12
文件,设置证书密钥。生成 Provisioning Profile 文件。
Download
生成 Provisioning Profile 文件。按照以下步骤,在声网控制台上传消息推送证书等信息:
登录声网控制台,点击左侧导航栏项目管理。
选择需要开通即时通讯服务的项目,点击配置。
在服务配置页面,点击即时通讯中的配置。
选择功能配置 > 推送证书。在证书管理页面,点击添加推送证书,在弹出的对话框中选择苹果,并配置如下字段,完成后点击保存:
打开 Xcode,点击 Targets > Capability > Push Notifications 开启消息推送权限。
将证书名称传递给 SDK。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 注册推送
[application registerForRemoteNotifications];
// 初始化选项,并设置 App Key
AgoraOptions *options = [AgoraOptions optionsWithAppkey:@"XXXX#XXXX"];
// 填写上传证书时设置的名称
options.apnsCertName = @"PushCertName";
[AgoraChatClient.sharedClient initializeSDKWithOptions:options];
return YES;
}
Device Token 注册后,iOS 系统会通过以下方式将 Device Token 回调给你,你需要将 Device Token 传给 SDK。
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[AgoraChatClient.sharedClient registerForRemoteNotificationsWithDeviceToken:deviceToken completion:^(AgoraError *aError) {
if (aError) {
NSLog(@"bind deviceToken error: %@", aError.errorDescription);
}
}];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"Register Remote Notifications Failed");
}
为优化用户在处理大量推送通知时的体验,即时通讯 IM 在 app 和会话层面提供了推送通知方式和免打扰模式的细粒度选项。
推送通知方式
推送通知方式参数 |
描述 |
应用范围 |
All |
接收所有离线消息的推送通知。 |
App 或单聊/群聊会话 |
MentionOnly |
仅接收提及某些用户的消息的推送通知。 该参数推荐在群聊中使用。若提及一个或多个用户,需在创建消息时对 ext 字段传 "em_at_list":["user1", "user2" ...];若提及所有人,对该字段传 "em_at_list":"all"。 |
|
NONE |
不接收离线消息的推送通知。 |
会话级别的推送通知方式设置优先于 app 级别的设置,未设置推送通知方式的会话默认采用 app 的设置。
例如,假设 app 的推送方式设置为 MentionOnly
,而指定会话的推送方式设置为 All
。你会收到来自该会话的所有推送通知,而对于其他会话来说,你只会收到提及你的消息的推送通知。
免打扰模式
你可以在 app 级别指定免打扰时间段和免打扰时长,即时通讯 IM 在这两个时间段内不发送离线推送通知。若既设置了免打扰时间段,又设置了免打扰时长,免打扰模式的生效时间为这两个时间段的累加。
免打扰时间参数的说明如下表所示:
免打扰时间参数 | 描述 | 应用范围 |
---|---|---|
silentModeStartTime & silentModeEndTime |
免打扰时间段,精确到分钟,格式为 HH:MM-HH:MM,例如 08:30-10:00。该时间为 24 小时制,免打扰时间段的开始时间和结束时间中的小时数和分钟数的取值范围分别为 [00,23] 和 [00,59]。免打扰时间段的设置说明如下:
|
仅用于 app 级别,对单聊或群聊会话不生效。 |
silentModeDuration |
免打扰时长,单位为毫秒。免打扰时长的取值范围为 [0,604800000],0 表示该参数无效,604800000 表示免打扰模式持续 7 天。与免打扰时间段的设置长久有效不同,该参数为一次有效。 |
App 或单聊/群聊会话。 |
推送通知方式与免打扰时间设置之间的关系
对于 app 和 app 中的所有会话,免打扰模式的设置优先于推送通知方式的设置。例如,假设在 app 级别指定了免打扰时间段,并将指定会话的推送通知方式设置为 All
。免打扰模式与推送通知方式的设置无关,即在指定的免打扰时间段内,你不会收到任何推送通知。
或者,假设为会话指定了免打扰时间段,而 app 没有任何免打扰设置,并且其推送通知方式设置为 All
。在指定的免打扰时间段内,你不会收到来自该会话的任何推送通知,而所有其他会话的推送保持不变。
你可以调用 setSilentModeForAll
设置 app 级别的推送通知,并通过指定 AgoraChatSilentModeParam
字段设置推送通知方式和免打扰模式,如下代码示例所示:
// 设置推送通知方式为 `MentionOnly`。
AgoraChatSilentModeParam *param = [[AgoraChatSilentModeParam alloc]initWithParamType:AgoraChatSilentModeParamTypeRemindType];
param.remindType = AgoraChatPushRemindTypeMentionOnly;
// 设置 app 的离线推送通知。
[[AgoraChatClient sharedClient].pushManager setSilentModeForAll:param completion:^(AgoraChatSilentModeResult *aResult, AgoraChatError *aError) {
if (aError) {
NSLog(@"setSilentModeForAll error---%@",aError.errorDescription);
}
}];
// 设置离线推送免打扰时长为 15 分钟。
AgoraChatSilentModeParam *param = [[AgoraChatSilentModeParam alloc]initWithParamType:AgoraChatSilentModeParamTypeDuration];
param.silentModeDuration = 15;
//设置离线推送的免打扰时间段为 8:30 到 15:00。
AgoraChatSilentModeParam *param = [[AgoraChatSilentModeParam alloc]initWithParamType:AgoraChatSilentModeParamTypeInterval];
param.silentModeStartTime = [[AgoraChatSilentModeTime alloc]initWithHours:8 minutes:30];
param.silentModeEndTime = [[AgoraChatSilentModeTime alloc]initWithHours:15 minutes:0];
你可以调用 getSilentModeForAllWithCompletion
获取 app 级别的推送通知设置,如以下代码示例所示:
[[AgoraChatClient sharedClient].pushManager getSilentModeForAllWithCompletion:^(AgoraChatSilentModeResult *aResult, AgoraChatError *aError) {
if (!aError) {
// 获取 app 的推送通知方式的设置。
AgoraChatPushRemindType remindType = aResult.remindType;
// 获取 app 的离线推送免打扰过期的 Unix 时间戳。
NSTimeInterval ex = aResult.expireTimestamp;
// 获取 app 的离线推送免打扰时间段的开始时间。
AgoraChatSilentModeTime *startTime = aResult.silentModeStartTime;
// 获取 app 的离线推送免打扰时间段的结束时间。
AgoraChatSilentModeTime *endTime = aResult.silentModeEndTime;
}else{
NSLog(@"getSilentModeForAll error---%@",aError.errorDescription);
}
}];
你可以调用 setSilentModeForConversation
方法设置指定会话的推送通知,并通过指定 SilentModeParam
字段设置推送通知方式和免打扰模式,如以下代码示例所示:
// 设置推送通知方式为 `MentionOnly`。
AgoraChatSilentModeParam *param = [[AgoraChatSilentModeParam alloc]initWithParamType:AgoraChatSilentModeParamTypeRemindType];
param.remindType = AgoraChatPushRemindTypeMentionOnly;
// 设置离线推送免打扰时长为 15 分钟。
AgoraChatSilentModeParam *param = [[AgoraChatSilentModeParam alloc]initWithParamType:AgoraChatSilentModeParamTypeDuration];
param.silentModeDuration = 15;
// 设置会话的离线推送免打扰模式。目前,暂不支持设置会话免打扰时间段。
AgoraChatConversationType conversationType = AgoraChatConversationTypeGroupChat;
[[AgoraChatClient sharedClient].pushManager setSilentModeForConversation:@"conversationId" conversationType:conversationType params:param completion:^(AgoraChatSilentModeResult *aResult, AgoraChatError *aError) {
if (aError) {
NSLog(@"setSilentModeForConversation error---%@",aError.errorDescription);
}
}];
你可以调用 getSilentModeForConversation
获取指定会话的推送通知设置,如以下代码示例所示:
[[AgoraChatClient sharedClient].pushManager getSilentModeForConversation:@"conversationId" conversationType:AgoraChatConversationTypeChat completion:^(AgoraChatSilentModeResult * _Nullable aResult, AgoraChatError * _Nullable aError) {
}];
你可以在每次调用中最多获取 20 个会话的推送通知设置。
如果会话继承了 app 设置或其推送通知设置已过期,则返回的字典不包含此会话。
你可以调用 getSilentModeForConversations
获取多个会话的推送通知设置,如以下代码示例所示:
NSArray *conversations = @[conversation1,conversation2];
[[AgoraChatClient sharedClient].pushManager getSilentModeForConversations:conversationArray completion:^(NSDictionary<NSString*,AgoraChatSilentModeResult*>*aResult, AgoraChatError *aError) {
if (aError) {
NSLog(@"getSilentModeForConversations error---%@",aError.errorDescription);
}
}];
你可以调用 clearRemindTypeForConversation
方法清除指定会话的推送通知方式的设置。清除后,默认情况下,此会话会继承 app 的设置。
以下代码示例显示了如何清除会话的推送通知方式的设置:
[[AgoraChatClient sharedClient].pushManager clearRemindTypeForConversation:@"" conversationType:conversationType completion:^(AgoraChatSilentModeResult *aResult, AgoraChatError *aError) {
if (aError) {
NSLog(@"clearRemindTypeForConversation error---%@",aError.errorDescription);
}
}];
你可以调用 updatePushDisplayName
设置推送通知中显示的昵称,如以下代码示例所示:
[AgoraChatClient.sharedClient.pushManager updatePushDisplayName:@"displayName" completion:^(NSString * aDisplayName, AgoraChatError * aError) {
if (aError)
{
NSLog(@"update push display name error: %@", aError.errorDescription);
}
}];
你也可以调用 updatePushDisplayStyle
设置推送通知的显示样式,如下代码示例所示:
// 设置为简单样式 `AgoraPushDisplayStyleSimpleBanner`,只显示 "你有一条新消息"。若要显示消息内容,需设置为 `AgoraPushDisplayStyleMessageSummary`。
[AgoraChatClient.sharedClient.pushManager updatePushDisplayStyle:AgoraPushDisplayStyleSimpleBanner completion:^(AgoraChatError * aError)
{
if(aError)
{
NSLog(@"update display style error --- %@", aError.errorDescription);
}
}];
你可以调用 getPushNotificationOptionsFromServerWithCompletion
方法获取推送通知中的显示属性,如以下代码示例所示:
[[AgoraChatClient sharedClient] getPushNotificationOptionsFromServerWithCompletion:^(AgoraChatPushOptions *aOptions, AgoraChatError *aError) {
if (!aError) {
// 获取推送通知中的显示昵称。
NSString *displayName = aOptions.displayName;
// 获取推送通知的显示样式。
AgoraChatPushDisplayStyle displayStyle = aOptions.displayStyle;
}
}];
如果用户启用自动翻译功能并发送消息,SDK 会同时发送原始消息和翻译后的消息。
推送通知与翻译功能协同工作。作为接收方,你可以设置你在离线时希望接收的推送通知的首选语言。如果翻译消息的语言符合你的设置,则翻译消息显示在推送通知中;否则,将显示原始消息。
以下代码示例显示了如何设置和获取推送通知的首选语言:
// 设置离线推送的首选语言。
[[AgoraChatClient sharedClient].pushManager setPreferredNotificationLanguage:@"EU" completion:^(AgoraChatError *aError) {
if (aError) {
NSLog(@"setPushPerformLanguageCompletion error---%@",aError.errorDescription);
}
}];
// 获取设置的离线推送的首选语言。
[[AgoraChatClient sharedClient].pushManager getPreferredNotificationLanguageCompletion:^(NSString *aLanguageCode, AgoraChatError *aError) {
if (!aError) {
NSLog(@"getPushPerformLanguage---%@",aLanguageCode);
}
}];
即时通讯 IM 支持自定义推送通知模板。使用前,你可以参考以下步骤为用户创建和提供推送模板:
登录声网控制台,点击左侧导航栏中的项目管理。
选择需要开通即时通讯服务的项目,点击配置。
在服务配置页面,点击 即时通讯IM 框的配置。
在左侧导航栏,选择功能配置 > 推送模板并单击添加推送模板,在弹出的对话框中配置字段,如下图所示。
创建推送模板后,用户可以在发送消息时选择使用此模板,代码示例如下所示。
// 下面以文本消息为例,其他类型的消息设置方法相同。
AgoraChatTextMessageBody *body = [[AgoraChatTextMessageBody alloc]initWithText:@"test"];
AgoraChatMessage *message = [[AgoraChatMessage alloc]initWithConversationID:@"conversationId" from:@"currentUsername" to:@"conversationId" body:body ext:nil];
// 将在声网控制台上创建的推送模板设置为默认推送模板。
NSDictionary *pushObject = @{
@"name":@"templateName",// // 设置推送模板名称。
@"title_args":@[@"titleValue1"],// 设置模板名称变量。
@"content_args":@[@"contentValue1"]// 设置模板内容变量。
};
message.ext = @{
@"em_push_template":pushObject,
};
message.chatType = AgoraChatTypeChat;
[[AgoraChatClient sharedClient].chatManager sendMessage:message progress:nil completion:nil];
如果现有的模板不能满足你的要求,你还可以自定义推送通知。
向推送中添加你自己的业务字段以满足业务需求,比如通过这条推送跳转到某个活动页面。
TextMessageBody *body = [[TextMessageBody alloc] initWithText:@"test"];
Message *message = [[Message alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_apns_ext":@{@"extern":@"custom string"}};
message.chatType = AgoraChatTypeChat;
[AgoraChatClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 | 描述 |
---|---|
body |
推送消息内容。 |
ConversationID |
消息所属的会话 ID。 |
from |
消息发送方的用户 ID。 |
to |
消息接收方的用户 ID。 |
em_apns_ext |
消息扩展字段。 |
extern |
消息扩展具体内容。 |
解析的内容如下:
{
"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。 |
参考如下代码,自定义推送消息显示内容:
TextMessageBody *body = [[TextMessageBody alloc] initWithText:@"test"];
Message *message = [[Message alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_apns_ext":@{@"em_push_content":@"custom push content"}};
message.chatType = AgoraChatTypeChat;
[AgoraChatClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 | 描述 |
---|---|
body |
推送消息内容。 |
ConversationID |
消息所属的会话 ID。 |
from |
消息发送方的用户 ID。 |
to |
消息接收方的用户 ID。 |
em_apns_ext |
消息扩展字段。 |
em_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 中,并在推送中配置使用的音频文件名称。详见苹果官方文档。
TextMessageBody *body = [[TextMessageBody alloc] initWithText:@"test"];
Message *message = [[Message alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_apns_ext":@{@"em_push_sound":@"custom.caf"}};
message.chatType = AgoraChatTypeChat;
[AgoraChatClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 | 描述 |
---|---|
body |
推送消息内容。 |
ConversationID |
消息所属的会话 ID。 |
from |
消息发送方的用户 ID。 |
to |
消息接收方的用户 ID。 |
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。消息唯一标识符。 |
设置强制推送后,用户发送消息时会忽略接收方的免打扰设置,不论是否处于免打扰时间段都会正常向接收方推送消息。
TextMessageBody *body = [[TextMessageBody alloc] initWithText:@"test"];
Message *message = [[Message alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_force_notification":@YES};
message.chatType = AgoraChatTypeChat;
[AgoraChatClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 | 描述 |
---|---|
body |
推送消息内容。 |
ConversationID |
消息所属的会话 ID。 |
from |
消息发送方的用户 ID。 |
to |
消息接收方的用户 ID。 |
em_force_notification |
是否为强制推送:
该字段名固定,不可修改。 |
发送静默消息指发送方在发送消息时设置不推送消息,即用户离线时,即时通讯 IM 服务不会通过第三方厂商的消息推送服务向该用户的设备推送消息通知。因此,用户不会收到消息推送通知。当用户再次上线时,会收到离线期间的所有消息。
发送静默消息和免打扰模式下均为不推送消息,区别在于发送静默消息为发送方在发送消息时设置,而免打扰模式为接收方设置在指定时间段内不接收推送通知。
TextMessageBody *body = [[TextMessageBody alloc] initWithText:@"test"];
Message *message = [[Message alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_ignore_notification":@YES};
message.chatType = AgoraChatTypeChat;
[AgoraChatClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 | 描述 |
---|---|
body |
推送消息内容。 |
ConversationID |
消息所属的会话 ID。 |
from |
消息发送方的用户 ID。 |
to |
消息接收方的用户 ID。 |
em_ignore_notification |
是否发送静默消息:
|
如果你的目标平台是 iOS 10.0 或以上版本,你可以参考如下代码,实现 UNNotificationServiceExtension
的扩展功能。
TextMessageBody *body = [[TextMessageBody alloc] initWithText:@"test"];
Message *message = [[Message alloc] initWithConversationID:conversationId from:currentUsername to:conversationId body:body ext:nil];
message.ext = @{@"em_apns_ext":@{@"em_push_mutable_content":@YES}};
message.chatType = AgoraChatTypeChat;
[AgoraChatClient.sharedClient.chatManager sendMessage:message progress:nil completion:nil];
参数 | 描述 |
---|---|
body |
推送消息内容。 |
ConversationID |
消息所属的会话 ID。 |
from |
消息发送方的用户 ID。 |
to |
消息接收方的用户 ID。 |
em_apns_ext |
消息扩展字段,该字段名固定,不可修改。该字段用于配置富文本推送通知,包含自定义字段。 |
em_push_mutable_content |
是否使用富文本推送通知(em_apns_ext ):
|
解析的内容如下:
{
"aps":{
"alert":{
"body":"test"
},
"badge":1,
"sound":"default",
"mutable-content":1
},
"f":"6001",
"t":"6006",
"m":"373360335316321408"
}
参数 | 描述 |
---|---|
body |
推送消息内容。 |
badge |
角标数。 |
sound |
提示铃声。 |
mutable-content |
设置为 1 表示激活 UNNotificationServiceExtension。 |
f |
消息发送方的用户 ID。 |
t |
消息接收方的用户 ID。 |
m |
消息 ID。 |