logo
即时通讯
客户端 SDK
发布日志
升级指南
当前页

多端登录


功能简介

ZIM SDK 支持配置自定义多端登录,即用户同一个账号可在多个平台上同时登录,满足用户的会话、消息、群组等数据互通。

说明
  • 如需使用此功能,请开通专业版或旗舰版套餐,并联系技术支持开通服务并配置登录策略。
  • 本功能仅支持 2.11.0 及以上版本的 SDK 使用。

常见的登录策略

多端登录可支持在 Android、iOS、HarmonyOS、Windows、macOS、Linux、iPadOS、Web、小程序等 9 个平台上配置,其中:

  • 支持在 Windows、macOS、Linux、Android、HarmonyOS、iOS、iPadOS 平台配置多设备登录,一个账号在同一时间只能在最多 10 台设备上进行登录。
  • 在 Web 平台配置多实例登录,最多不超过 10 个登录实例。

以下为 ZIM SDK 支持的三种登录策略,即单平台登录、双平台登录以及多平台登录:

登录策略具体说明
单平台登录(默认)仅支持用户同时在 1 个平台上登录帐号。如果在其他平台上登录帐号,原平台上的账号会被退出。
双平台登录支持用户在 Windows、Mac、Linux、Android、HarmonyOS、iOS 和 iPad 的其中 1 个平台上登录帐号,并同时保持帐号在 Web 平台在线。
多平台登录是指支持用户同时在 Windows、Mac、Linux、Android、HarmonyOS、iOS、iPad、Web、小程序多平台登录帐号,支持以下配置:
  • 同一平台同时多设备、实例登录。
  • 配置互踢逻辑,当前仅支持 Android、HarmonyOS、iOS 设备互踢,Windows、Mac 设备互踢。

实现流程

前往 ZEGO 控制台开通多端登录服务,详情请参考控制台文档 服务配置 - 即时通讯 - 多端登录配置。开通后,即可在多端调用 login 登录 ZIM SDK,实现流程与单端登录无异。如何登录,详情请参考 实现基本消息收发 的“登录 ZIM“。

当登录设备已达到策略规定的上限时,如果在新设备登录帐号,原设备中最早登录的帐号会被踢下线,并通过 onConnectionStateChanged 回调得知 event 为 KickedOut 。例如:登录策略规定最多只能在 3 台设备上登录,已在设备 A、B、C(按登录时间排序)登录,如果在设备 D 上登录帐号,则设备 A 上的帐号会被踢下线。

当帐号被踢下线后,建议调用 logout 接口登出 ZIM 服务,用户界面切换为登录界面。

多端登录对其他功能的影响

配置多端登录后,以下功能的代码也需要做相应调整。

用户信息管理

ZIM SDK 为多端登录用户提供了用户信息同步的功能。当用户在一端通过 updateUserNameupdateUserAvatarUrlupdateUserExtendedData 接口更新了自己的信息后,其他在线客户端可通过注册 onUserInfoUpdated 事件监听用户信息被修改。

onUserInfoUpdated 示例

Untitled
ZIMEventHandler.onUserInfoUpdated = (ZIM zim, ZIMUserFullInfo info){
    // 您可以从info中获取以下信息:用户ID、用户名、用户头像、用户附加字段
    String userID = info.baseInfo.userID;
    String userName = info.baseInfo.userName;
    String userAvatarUrl = info.userAvatarUrl;
    String extendedData = info.extendedData;
};
1
Copied!

会话管理

删除单个服务端会话

当用户在一端通过 deleteConversation 接口删除服务端会话后(即 isAlsoDeleteServerConversation 为 true),其他在线客户端可通过注册 onConversationChanged 事件监听会话被删除。

onConversationChanged 示例

Untitled
ZIMEventHandler.onConversationChanged = (ZIM zim, List<ZIMConversationChangeInfo> conversationChangeInfoList){
    for (ZIMConversationChangeInfo convInfo : conversationChangeInfoList) {
        if (convInfo.event == ZIMConversationEvent.delete) {
       // 该对话已被删除
        }
    }
};
1
Copied!

删除全部服务端会话

当用户在一端通过 deleteAllConversations 接口删除全部服务端会话后(即 isAlsoDeleteServerConversation 为 true),其他客户端可通过 onConversationsAllDeleted 事件监听全部会话被删除。

onConversationsAllDeleted 处理示例

Untitled
ZIMEventHandler.onConversationChanged = (ZIM zim, List<ZIMConversationChangeInfo> conversationChangeInfoList){
    for (ZIMConversationChangeInfo convInfo : conversationChangeInfoList) {
        if (convInfo.event == ZIMConversationEvent.delete) {
        // 该对话已被删除
        }
    }
};
1
Copied!

清楚全部会话未读

当用户在一端通过 clearConversationTotalUnreadMessageCount 清除全部会话未读时,其他客户端可通过 onConversationTotalUnreadMessageCountUpdated 事件监听所有会话的未读都被清零的通知。

onConversationTotalUnreadMessageCountUpdated 处理示例

Untitled
ZIMEventHandler.onConversationsAllDeleted = (
      ZIM zim, ZIMConversationsAllDeletedInfo info){
        // 所有对话已被另一个客户删除
}
1
Copied!

消息管理

消息同步

当用户登录新设备后,SDK 不会自动将旧设备中的已有消息同步到新设备上,用户需要主动调用 queryHistoryMessage 接口,才能获取存储于 ZIM 服务端的消息,详情请参考 获取历史消息。对于存储于旧设备的本地消息,则无法获取。

删除服务端消息

当用户在一端通过 deleteMessagesdeleteAllMessagedeleteAllConversationMessages 接口删除会话的服务端消息后(即 isAlsoDeleteServerMessage 为 true),其他在线客户端可通过注册 onMessageDeleted 事件监听消息被删除。

调用接口示例
Untitled
ZIMEventHandler.onMessageDeleted = (ZIM zim, ZIMMessageDeletedInfo deletedInfo){
    if (deletedInfo.messageDeleteType == ZIMMessageDeleteType.messageListDeleted)
        {
            // 会话中的多条消息已被删除
            for (var message in messageList) {
                // 遍历每条已删除的消息
            }
        } else if (deletedInfo.messageDeleteType ==
                   ZIMMessageDeleteType.conversationAllMessagesDeleted)
        {
            // 会话中的所有消息已被删除
        } else if (deletedInfo.messageDeleteType ==
                   ZIMMessageDeleteType.allConversationMessagesDeleted)
        {
            // 所有会话中的消息都已被删除
        }
}
1
Copied!

设置消息回执已读

当用户在一端通过 sendMessageReceiptsReadsendConversationMessageReceiptRead 接口设置消息回执已读后,其他在线客户端可通过注册 messageReceiptChangedonConversationMessageReceiptChanged 事件监听本帐号已设置消息回执为已读。

调用接口示例
Untitled
ZIMEventHandler.onMessageReceiptChanged = (ZIM zim, List<ZIMMessageReceiptInfo> infos){
    for (ZIMMessageReceiptInfo info : infos) {
        if (info.isSelfOperated) {
            // 用户已将消息回执设置为已读
        }
    }
};

ZIMEventHandler.onConversationMessageReceiptChanged = (ZIM zim, List<ZIMMessageReceiptInfo> infos){
    for (ZIMMessageReceiptInfo info : infos) {
        if (info.isSelfOperated) {
            // 用户已将消息回执设置为已读
        }
    }
};
1
Copied!

房间管理

房间模块相关接口和事件不支持多端登录。用户在 A 设备加入房间后,然后在 B 设备再加入相同的房间后,会把 A 设备踢出房间,A 设备会通过 onRoomStateChanged 回调收到 eventKickedOutByMultiDevice

Untitled
ZIMEventHandler.onRoomStateChanged = (ZIM zim, ZIMRoomState state, ZIMRoomEvent event,
    Map extendedData, String roomID){
        if (state == ZIMRoomState.disconnected &&
            event == ZIMRoomEvent.kickedOut) {
        // 由于多设备登录而被踢出房间
        }
    };
1
Copied!

群组管理

在开通多端登录服务后,ZIM SDK 会自动在多端设备之间同步群组相关数据。

呼叫邀请管理

当用户同时登录设备 A 和 B,用户收到呼叫邀请,在设备 A 上接受邀请(调用 callAccept )或者拒绝邀请(调用 callReject ) 后:

  1. 设备 A 可以通过相关操作的回调( ZIMCallAcceptanceSentResultZIMCallRejectionSentResult )得知操作结果,关闭邀请弹窗,实现其他业务操作;
  2. 设备 B 应当通过 onCallUserStateChanged 回调,得知本用户的呼叫用户状态( ZIMCallUserState )是 Accepted 还是 Rejected,关闭邀请弹窗,实现其他业务操作

各个设备能收到该呼叫内的用户状态变更事件 onCallUserStateChanged 如下表所示:

callUserState设备 A设备 B
Inviting✔️✔️
Received✔️✔️
Accepted✔️✔️
Rejected✔️✔️
Timeout
Cancelled
Quit✔️
调用接口示例
Untitled
String selfUserID = "user_id";
String currentCallID = "call_id";

ZIMCallAcceptConfig acceptConfig;
acceptConfig.extendedData = "extra_1";

ZIMCallRejectConfig rejectConfig;
rejectConfig.extendedData = "extra_1";

// 设备A接受邀请
ZIM.getInstance()!.callAccept(currentCallID, acceptConfig).then((value) {
    // 关闭呼叫等待操作的弹窗。
}).catchError((onError){
    // 处理异常
});

// 设备A拒绝邀请
ZIM.getInstance()!.callReject(currentCallID, rejectConfig).then((value) {
    // 关闭呼叫等待操作的弹窗。
}).catchError((onError){
    // 处理异常
});

// 设备B监听onCallUserStateChanged事件
ZIMEventHandler.onCallUserStateChanged = (ZIM zim, ZIMCallUserStateChangeInfo callUserStateChangeInfo, String callID){
    if (currentCallID == callID) {
         // 当设备A接受或拒绝时,关闭呼叫等待操作的弹窗。
    }
};
1
Copied!

Previous

用户管理

Next

离线登录