使用 ZIM SDK 实现离线推送
2026-04-02
ZIM 支持在发送单聊消息、发送群组消息、发起呼叫邀请等场景,使用离线推送消息的功能。
实现流程
场景 1:发送 “单聊消息” 或 “群组消息” 时使用离线推送功能
-
首先开发者需要通过 ZIMPushConfig 对象,设置离线推送标题、内容、以及其他自定义属性。
-
然后通过 ZIMMessageSendConfig 对象的
pushConfig参数,配置离线消息的相关配置等。 -
发送方调用 sendMessage,传入 “sentConfig”,向接收方发送单聊消息或者向群组发送群聊消息。
-
接收方或者群组内的用户,如果处于离线状态,将会在上线后,接收到发送方之前发送的离线消息。
ZIMTextMessage textMessage = new ZIMTextMessage();
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源 ID,非必填";
ZIMMessageSendConfig sentConfig = new ZIMMessageSendConfig();
sentConfig.pushConfig = pushConfig;
zim.sendMessage(textMessage, "myUserID", ZIMConversationType.PEER, sentConfig, new ZIMMessageSentCallback() {
@Override
public void onMessageSent(ZIMMessage message, ZIMError errorInfo) {
}
@Override
public void onMessageAttached(ZIMMessage message) {
}
});ZIMTextMessage textMessage = new ZIMTextMessage();
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源 ID,非必填";
ZIMMessageSendConfig sentConfig = new ZIMMessageSendConfig();
sentConfig.pushConfig = pushConfig;
zim.sendMessage(textMessage, "myUserID", ZIMConversationType.PEER, sentConfig, new ZIMMessageSentCallback() {
@Override
public void onMessageSent(ZIMMessage message, ZIMError errorInfo) {
}
@Override
public void onMessageAttached(ZIMMessage message) {
}
});ZIMPushConfig *pushConfig = [ZIMPushConfig alloc] init];
pushConfig.title = @"离线推送标题";
pushConfig.content = @"离线推送内容";
pushConfig.payload = @"自定义透传字段,非必填";
pushConfig.resourcesID = @"资源ID";
ZIMMessageSendConfig *sendConfig = [ZIMMessageSendConfig alloc] init];
sendConfig.pushConfig = pushConfig;
[zim sendMessage:zimMessage toConversationID:conversationID conversationType:ZIMConversationTypePeer config:sendConfig callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];ZIMPushConfig *pushConfig = [ZIMPushConfig alloc] init];
pushConfig.title = @"离线推送标题";
pushConfig.content = @"离线推送内容";
pushConfig.payload = @"自定义透传字段,非必填";
pushConfig.resourcesID = @"资源ID";
ZIMMessageSendConfig *sendConfig = [ZIMMessageSendConfig alloc] init];
sendConfig.pushConfig = pushConfig;
[zim sendMessage:zimMessage toConversationID:conversationID conversationType:ZIMConversationTypePeer config:sendConfig callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];zim::ZIMPushConfig pushConfig;
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源ID";
zim::ZIMMessageSendConfig sendConfig;
sendConfig.pushConfig = pushConfig;
zim::ZIMMessage* message = nullptr;
zim::ZIMTextMessage text_message;
text_message.message = "message";
message = &text_message;
zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) { int i = 0; });
// 单聊时,toConversationID 即是对方的 userID;群组时,toConversationID 即是群组的 groupID。
zim_->sendMessage(message, "toConversationID", type, sendConfig, notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) { int i = 0; });zim::ZIMPushConfig pushConfig;
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源ID";
zim::ZIMMessageSendConfig sendConfig;
sendConfig.pushConfig = pushConfig;
zim::ZIMMessage* message = nullptr;
zim::ZIMTextMessage text_message;
text_message.message = "message";
message = &text_message;
zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) { int i = 0; });
// 单聊时,toConversationID 即是对方的 userID;群组时,toConversationID 即是群组的 groupID。
zim_->sendMessage(message, "toConversationID", type, sendConfig, notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) { int i = 0; });ZIMPushConfig pushConfig = ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源ID";
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
sendConfig.pushConfig = pushConfig;
ZIM.getInstance()!.sendMessage(ZIMTextMessage(message: 'message'), 'toUserID', ZIMConversationType.peer, sendConfig)
.then((value) => {})
.onError((error, stackTrace) => {});ZIMPushConfig pushConfig = ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源ID";
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
sendConfig.pushConfig = pushConfig;
ZIM.getInstance()!.sendMessage(ZIMTextMessage(message: 'message'), 'toUserID', ZIMConversationType.peer, sendConfig)
.then((value) => {})
.onError((error, stackTrace) => {});const pushConfig: ZIMPushConfig = {
title = "离线推送标题";
content = "离线推送内容";
payload = "自定义透传字段,非必填";
resourcesID = "资源 ID,非必填";
}
const sendConfig: ZIMMessageSendConfig = {
priority: 2,
pushConfig: pushConfig
};
const toUserID = '';
const messageTextObj: ZIMMessage = { type: 1, message: '文本消息内容' };
zim.sendMessage(messageTextObj, toUserID, 0, sendConfig)
.then((res: ZIMMessageSentResult) => {
// 发送成功
})
.catch((err: ZIMError) => {
// 发送失败
});const pushConfig: ZIMPushConfig = {
title = "离线推送标题";
content = "离线推送内容";
payload = "自定义透传字段,非必填";
resourcesID = "资源 ID,非必填";
}
const sendConfig: ZIMMessageSendConfig = {
priority: 2,
pushConfig: pushConfig
};
const toUserID = '';
const messageTextObj: ZIMMessage = { type: 1, message: '文本消息内容' };
zim.sendMessage(messageTextObj, toUserID, 0, sendConfig)
.then((res: ZIMMessageSentResult) => {
// 发送成功
})
.catch((err: ZIMError) => {
// 发送失败
});场景 2:发送呼叫邀请时使用离线推送功能
-
开发者通过 ZIMPushConfig 对象,设置离线推送标题、内容、以及其他自定义属性。
-
然后通过 ZIMCallInviteConfig 对象的
pushConfig参数,配置离线消息的相关配置等。 -
发送方调用 callInvite,传入 “callInviteConfig”,发起呼叫邀请。
-
被邀请的用户若处于离线状态,将会收到对应的离线推送,上线后,若呼叫邀请还未结束,将会收到 onCallInvitationReceived 的回调。
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源 ID,非必填";
ZIMCallInviteConfig callInviteConfig = new ZIMCallInviteConfig();
callInviteConfig.pushConfig = pushConfig;
ArrayList<String> invitees = new ArrayList<>();
invitees.add("userA");
invitees.add("userB");
zim.callInvite(invitees, callInviteConfig, new ZIMCallInvitationSentCallback() {
@Override
public void onCallInvitationSent(String callID, ZIMCallInvitationSentInfo info, ZIMError errorInfo) {
}
});ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源 ID,非必填";
ZIMCallInviteConfig callInviteConfig = new ZIMCallInviteConfig();
callInviteConfig.pushConfig = pushConfig;
ArrayList<String> invitees = new ArrayList<>();
invitees.add("userA");
invitees.add("userB");
zim.callInvite(invitees, callInviteConfig, new ZIMCallInvitationSentCallback() {
@Override
public void onCallInvitationSent(String callID, ZIMCallInvitationSentInfo info, ZIMError errorInfo) {
}
});ZIMPushConfig *pushConfig = [ZIMPushConfig alloc] init];
pushConfig.title = @"离线推送标题";
pushConfig.content = @"离线推送内容";
pushConfig.payload = @"自定义透传字段,非必填";
pushConfig.resourcesID = @"资源ID";
ZIMCallInviteConfig *callInviteConfig = [ZIMMessageSendConfig alloc] init];
callInviteConfig.pushConfig = pushConfig;
[[ZIM getInstance] callInviteWithInvitees:@[@"userA",@"userB"] config: callInviteConfig callback:^(NSString * _Nonnull callID, ZIMCallInvitationSentInfo * _Nonnull info, ZIMError * _Nonnull errorInfo) {
}];ZIMPushConfig *pushConfig = [ZIMPushConfig alloc] init];
pushConfig.title = @"离线推送标题";
pushConfig.content = @"离线推送内容";
pushConfig.payload = @"自定义透传字段,非必填";
pushConfig.resourcesID = @"资源ID";
ZIMCallInviteConfig *callInviteConfig = [ZIMMessageSendConfig alloc] init];
callInviteConfig.pushConfig = pushConfig;
[[ZIM getInstance] callInviteWithInvitees:@[@"userA",@"userB"] config: callInviteConfig callback:^(NSString * _Nonnull callID, ZIMCallInvitationSentInfo * _Nonnull info, ZIMError * _Nonnull errorInfo) {
}];zim::ZIMPushConfig pushConfig;
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源ID";
zim::ZIMCallInviteConfig callInviteConfig;
callInviteConfig.pushConfig = pushConfig;
zim_->callInvite(invitees, callInviteConfig, [=](std::string callID, zim::ZIMCallInvitationSentInfo info, zim::ZIMError errorInfo) {}); zim::ZIMPushConfig pushConfig;
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源ID";
zim::ZIMCallInviteConfig callInviteConfig;
callInviteConfig.pushConfig = pushConfig;
zim_->callInvite(invitees, callInviteConfig, [=](std::string callID, zim::ZIMCallInvitationSentInfo info, zim::ZIMError errorInfo) {}); ZIMPushConfig pushConfig = ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源ID";
ZIMCallInviteConfig callInviteConfig = ZIMCallInviteConfig();
callInviteConfig.pushConfig = pushConfig;
ZIM.getInstance()!.callInvite(["userA","userB"], callInviteConfig)
.then((value) {})
.catchError((onError){});ZIMPushConfig pushConfig = ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.payload = "自定义透传字段,非必填";
pushConfig.resourcesID = "资源ID";
ZIMCallInviteConfig callInviteConfig = ZIMCallInviteConfig();
callInviteConfig.pushConfig = pushConfig;
ZIM.getInstance()!.callInvite(["userA","userB"], callInviteConfig)
.then((value) {})
.catchError((onError){});const pushConfig: ZIMPushConfig = {
title: "离线推送标题",
content: "离线推送内容",
payload: "自定义透传字段,非必填",
resourcesID: "资源 ID,非必填",
}
const callInviteConfig: ZIMCallInviteConfig = {
mode: 0,
timeout: 90,
extendedData: '',
pushConfig: pushConfig
}
const invitees = ['xxxx']; // 被邀请人ID列表
zim.callInvite(invitees, callInviteConfig)
.then((res: ZIMCallInvitationSentResult) => {
const callID = res.callID;
// 操作成功
// 此处的 callID 是用户发起呼叫后,SDK 内部生成的 ID,用于唯一标识一次呼叫邀请;之后发起人取消呼叫、被邀请人接受/拒绝呼叫,都会使用此 callID
})
.catch((err: ZIMError) => {
// 操作失败
})const pushConfig: ZIMPushConfig = {
title: "离线推送标题",
content: "离线推送内容",
payload: "自定义透传字段,非必填",
resourcesID: "资源 ID,非必填",
}
const callInviteConfig: ZIMCallInviteConfig = {
mode: 0,
timeout: 90,
extendedData: '',
pushConfig: pushConfig
}
const invitees = ['xxxx']; // 被邀请人ID列表
zim.callInvite(invitees, callInviteConfig)
.then((res: ZIMCallInvitationSentResult) => {
const callID = res.callID;
// 操作成功
// 此处的 callID 是用户发起呼叫后,SDK 内部生成的 ID,用于唯一标识一次呼叫邀请;之后发起人取消呼叫、被邀请人接受/拒绝呼叫,都会使用此 callID
})
.catch((err: ZIMError) => {
// 操作失败
})场景 3:iOS 通知分组
开发者在通知发送端配置 ZIMPushConfig 的 threadID 参数,即可实现 iOS 离线推送的通知分组效果。
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.threadID = "通知分组标志";ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.threadID = "通知分组标志";ZIMPushConfig *pushConfig = [ZIMPushConfig alloc] init];
pushConfig.title = @"离线推送标题";
pushConfig.content = @"离线推送内容";
pushConfig.threadID = @"通知分组标志";ZIMPushConfig *pushConfig = [ZIMPushConfig alloc] init];
pushConfig.title = @"离线推送标题";
pushConfig.content = @"离线推送内容";
pushConfig.threadID = @"通知分组标志";zim::ZIMPushConfig pushConfig;
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.threadID = "通知分组标志";zim::ZIMPushConfig pushConfig;
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.threadID = "通知分组标志";ZIMPushConfig pushConfig = ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.threadID = "通知分组标志";ZIMPushConfig pushConfig = ZIMPushConfig();
pushConfig.title = "离线推送标题";
pushConfig.content = "离线推送内容";
pushConfig.threadID = "通知分组标志";const pushConfig: ZIMPushConfig = {
title: "离线推送标题",
content: "离线推送内容",
threadID: "通知分组标志",
}const pushConfig: ZIMPushConfig = {
title: "离线推送标题",
content: "离线推送内容",
threadID: "通知分组标志",
}场景 4:iOS 通知徽标数量
开发者可通过调用 updateUserBadge 接口更新徽标数量。
常见使用场景为:多端登录时,如果某端清除了某个会话未读消息数后,iOS 端的通知徽标数量需要同步减掉该会话的未读消息数。 比如,当前徽标数量为 10,清除的会话未读数为 8,那么可调用此接口更新徽标数量为 2。
zim.updateUserBadge(2, new ZIMUserBadgeUpdatedCallback() {
@Override
public void onUserBadgeUpdated(ZIMError errorInfo) {
}
});zim.updateUserBadge(2, new ZIMUserBadgeUpdatedCallback() {
@Override
public void onUserBadgeUpdated(ZIMError errorInfo) {
}
});[[ZIM getInstance] updateUserBadge:2 callback:^(ZIMError * _Nonnull errorInfo) {
}];[[ZIM getInstance] updateUserBadge:2 callback:^(ZIMError * _Nonnull errorInfo) {
}];zim_->updateUserBadge(2, [=](zim::ZIMError errorInfo) {}); zim_->updateUserBadge(2, [=](zim::ZIMError errorInfo) {}); ZIM.getInstance()!.updateUserBadge(2).then(() {
}).catchError((onError){
});ZIM.getInstance()!.updateUserBadge(2).then(() {
}).catchError((onError){
});zim.updateUserBadge(2)
.then(() => {
// 操作成功
})
.catch((err: ZIMError) => {
// 操作失败
});zim.updateUserBadge(2)
.then(() => {
// 操作成功
})
.catch((err: ZIMError) => {
// 操作失败
});