Log in from multiple devices
Updated
Log in to Agora Chat from multiple devices
Agora Chat supports logging in to the same account from up to 4 devices at the same time by default. You can increase the number of devices per platform up to 10 by going to Agora Console > Project management > Relevant project > Agora Chat configuration > Features > Multi Device.
In cases of multiple device login, all logged-in devices synchronize the following information and operations:
- Messages, including online messages, offline messages, push notifications (if the third-party push service is enabled, the offline device receives it), the corresponding receipts and read status, and so on;
- Friends and group-related operations;
- Message-thread-related operations;
- Conversation-related operations.
The following table summarizes the strategy of forcing other devices to log out and the automatic login security check in the single-device and multi-device login use-cases:
Single/multi-device login Forced logout strategy Automatic login security check
Single-device login
The newly logged-in device will force the current device to log out. The logged-out device will receive the AgoraChatClientDelegate#userAccountDidLoginFromOtherDevice event.
For devices that log in automatically, the device will automatically reconnect to the Agora server after going offline. If the reconnection is successful, the current logged-in device will be forced to log out by default (for multiple devices, the earliest logged-in device will be logged out). If you want to keep the current device logged in, contact support@agora.io. In this use-case, the device that logs in automatically won't be able to log in and will receive error 214, indicating that the number of currently logged-in devices exceeds the limit.
Multi-device login
If the number of logged-in devices on one end reaches the limit, the device that logged in the latest will force the device that logged in the earliest to log out. The logged-out device will receive the AgoraChatClientDelegate#userAccountDidLoginFromOtherDevice event. Agora Chat only supports forced logout for the devices on the same end.
| Single/multi-device login | Forced logout strategy |
|---|---|
| Single-device login | The newly logged-in device will force the current device to log out. The logged-out device will receive the onDisconnected event. |
| Multi-device login | If the number of logged-in devices on one end reaches the limit, the device that logged in the latest will force the device that logged in the earliest to log out. Agora Chat only supports forced logout for the devices on the same end. When multiple ends are logged in, the use of a fixed device ID affects the forced logout strategy. The SDK generates an ID as the unique device identifier. Previously, the SDK used a different random string as the device identifier for each opened tab. Starting from v1.3.1, the SDK has the ConnectionParameters#isFixedDeviceId parameter, which you can set to use a random device ID or a fixed device ID when initializing the SDK: - (Default) true: Use a fixed device ID. The device ID is stored in local storage. Even when multiple devices are logged in, only one tab can be opened in the same browser. If two are opened, the new tab will force the previous one offline. - false: Use a random device ID. Each tab uses a different device ID. When logging in with multiple devices, a user can open multiple tabs in the same browser. If the number of devices exceeds the set number, the newly opened tab will force the first opened tab offline. |
The Agora server provides a RESTful interface to force a specified account to log out from a single device.
Single/multi-device login Forced logout strategy Automatic login security check
Single-device login
The newly logged-in device will force the current device to log out. The logged-out device will receive the ConnectionEventHandler#onUserDidLoginTooManyDevice event.
For devices that log in automatically, the device will automatically reconnect to the Agora server after going offline. If the reconnection is successful, the current logged-in device will be forced to log out by default (for multiple devices, the earliest logged-in device will be logged out). If you want to keep the current device logged in, contact support@agora.io. In this use-case, the device that logs in automatically won't be able to log in and will receive error 214, indicating that the number of currently logged-in devices exceeds the limit.
Multi-device login
If the number of logged-in devices on one end reaches the limit, the device that logged in the latest will force the device that logged in the earliest to log out. The logged-out device will receive the ConnectionEventHandler#onUserDidLoginTooManyDevice event. Agora Chat only supports forced logout for the devices on the same end.
Single/multi-device login Forced logout strategy Automatic login security check
Single-device login
The newly logged-in device will force the current device to log out. The logged-out device will receive the ChatConnectEventListener#onUserDidLoginFromOtherDevice event.
For devices that log in automatically, the device will automatically reconnect to the Agora server after going offline. If the reconnection is successful, the current logged-in device will be forced to log out by default (for multiple devices, the earliest logged-in device will be logged out). If you want to keep the current device logged in, contact support@agora.io. In this use-case, the device that logs in automatically won't be able to log in and will receive error 214, indicating that the number of currently logged-in devices exceeds the limit.
Multi-device login
If the number of logged-in devices on one end reaches the limit, the device that logged in the latest will force the device that logged in the earliest to log out. The logged-out device will receive the ChatConnectEventListener#onUserDidLoginFromOtherDevice event. Agora Chat only supports forced logout for the devices on the same end.
Understand the tech
During initialization, the SDK generates a login ID to identify the device when multiple devices log in and push messages, and sends this ID to the server. The server automatically sends new messages to the user's logged-in device, monitors operations on other devices, and synchronizes multiple devices. The SDK provides the following multi-device use-case functions:
-
Get the login ID list of the other logged-in devices of the current user;
-
Get the list of online logged-in devices of the specified account;
-
Force the specified account to log out from a single device;
-
Force the specified account to log out from all devices;
-
Get operations on other devices.
-
Set the name of the login device;
-
Set the platform of the login device;
-
Get notified about multi-device synchronization.
Chat SDK generates a new unique login ID every time a user logs in and sends the ID to the server. The server automatically sends new messages to the device where the user logs in, and can automatically monitor friend or group operations on other devices.
Prerequisites
Before starting this procedure, initialize and connect the SDK to the server. See SDK quickstart for details.
Implement multi-device login
Get the login ID list of other logged-in devices of the current user
Call getSelfIdsOnOtherPlatform to get the login ID list of other logged-in devices, and then select the target login ID as the message recipient to send a message to the specified device.
AgoraChatClient.shared().contactManager?.getSelfIdsOnOtherPlatform(completion: { ids, err in
if err == nil,
let userId = ids?.first {
// Select a login ID as the message recipient. Create a text message, content is the message text, conversationId passes the login ID as the message recipient.
let textMessage = AgoraChatMessage(conversationId: userId, body: .text(content: "hello"), ext: nil)
AgoraChatClient.shared().chatManager?.send(textMessage, progress: nil, completion: { msg, e in
})
}
})Get the list of online logged-in devices for the specified account
Call getLoggedInDevicesFromServerWithToken to get the list of online logged-in devices for the specified account from the server by passing in the user ID and user token.
AgoraChatClient.shared().getLoggedInDevicesFromServer(withUserId: "userId", token: "token") { deviceConfigs, err in
if err == nil {
}
}Force the specified account to log out from a single device
Call kickDeviceWithUserId and pass in the user ID and user token to force the specified account to log out from a single logged-in device. Before calling this method, obtain the device ID through the AgoraChatClient#getLoggedInDevicesFromServer and AgoraChatDeviceInfo#resource methods. The logged-out device will receive the AgoraChatClientDelegate#userAccountDidLoginFromOtherDevice event.
You can also use this interface without logging in.
AgoraChatClient.shared().getLoggedInDevicesFromServer(withUserId: "userId", token: "token") { deviceConfigs, err in
if err == nil,
let resource = deviceConfigs?.first?.resource {
AgoraChatClient.shared().kickDevice(withUserId: "userId", token: "token", resource: resource) { e in
}
}
}Force the specified account to log out from all devices
Call kickAllDevicesWithUserId and pass in the user ID and user token to force the specified account to log out from all logged-in devices. The logged-out device will receive the AgoraChatClientDelegate#userAccountDidLoginFromOtherDevice event.
You can also use this interface without logging in.
AgoraChatClient.shared().kickAllDevices(withUserId: "userId", token: "token") { err in
}Get operations on other devices
Let's say that account A logs in on devices A and B at the same time and performs operations on device A. Device B will receive notifications corresponding to these operations.
You need to implement the AgoraChatMultiDevicesDelegate class to listen to operations on other devices, and then call the addMultiDevicesDelegate method to add multi-device listening.
extension AppDelegate: AgoraChatMultiDevicesDelegate {
func multiDevicesContactEventDidReceive(_ aEvent: AgoraChatMultiDevicesEvent, username aUsername: String, ext aExt: String?) {
switch aEvent {
//The current user deletes friends on other devices.
case .contactRemove:
break
//The current user accepts friend requests on other devices.
case .contactAccept:
break
//The current user rejects friend requests on other devices.
case .contactDecline:
break
//The current user adds a user to the blocklist on other devices.
case .contactBan:
break
//The current user removes a user from the blocklist on other devices.
case .contactAllow:
break
default:
break
}
}
func multiDevicesGroupEventDidReceive(_ aEvent: AgoraChatMultiDevicesEvent, groupId aGroupId: String, ext aExt: Any?) {
switch aEvent {
//The current user created a group on another device
case .groupCreate:
break
//The current user destroyed a group on another device
case .groupDestroy:
break
//The current user joined a group on another device
case .groupJoin:
break
//The current user left a group on another device
case .groupLeave:
break
//The current user initiated a group application on another device
case .groupApply:
break
//The current user accepted a group application on another device
case .groupApplyAccept:
break
//The current user rejected a group application on another device
case .groupApplyDecline:
break
//The current user invited group members on another device
case .groupInvite:
break
//The current user has accepted the invitation to join the group on other devices
case .groupInviteAccept:
break
//The current user has rejected the invitation to join the group on other devices
case .groupInviteDecline:
break
//The current user has kicked members out of the group on other devices
case .groupKick:
break
//The current user has added members to the group blocklist on other devices
case .groupBan:
break
//The current user has removed members from the group blocklist on other devices
case .groupAllow:
break
//The current user has blocked the group on other devices
case .groupBlock:
break
//The current user has unblocked the group on other devices
case .groupUnBlock:
break
//The current user has transferred group ownership on other devices
case .groupAssignOwner:
break
//The current user has added an administrator on other devices
case .groupAddAdmin:
break
//The current user has removed an administrator on other devices
case .groupRemoveAdmin:
break
//The current user has muted users on other devices
case .groupAddMute:
break
//The current user removes the mute on other devices
case .groupRemoveMute:
break
//The current user sets the group member custom attributes on other devices
case .groupMemberAttributesChanged:
break
default:
break
}
}
func multiDevicesChatThreadEventDidReceive(_ aEvent: AgoraChatMultiDevicesEvent, threadId aThreadId: String, ext aExt: Any?) {
switch aEvent {
case .chatThreadCreate:
//The current user creates a message thread on other devices.
break
case .chatThreadDestroy:
//The current user destroys the message thread on other devices.
break
case .chatThreadJoin:
//The current user joins the message thread on other devices.
break
case .chatThreadLeave:
//The current user leaves the message thread on other devices.
break
case .chatThreadUpdate:
//The current user updates the message thread on other devices.
break
case .chatThreadKick:
//The current user kicks a member out of the message thread on other devices.
break
default:
break
}
}
func multiDevicesConversationEvent(_ event: AgoraChatMultiDevicesEvent, conversationId: String, conversationType: AgoraChatConversationType) {
switch event {
case .conversationPinned:
//The current user pins a conversation on other devices.
break
case .conversationUnpinned:
//The current user unpins a conversation on other devices.
break
case .conversationDelete:
//The current user deletes a conversation on other devices.
break
//The current user updates the conversation mark on other devices, including adding and removing conversation marks.
case .conversationUpdateMark:
default:
break
}
}
func multiDevicesMessageBeRemoved(_ conversationId: String, deviceId: String) {
//The current user unidirectionally deletes message history of a conversation on other devices from the server.
}
}
//Add a multi-device listener.
AgoraChatClient.shared().addMultiDevices(delegate: self, queue: nil)