# Log in from multiple devices (/en/realtime-media/im/build/moderate-and-manage-client-behavior/multiple-device-login/android)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

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 `ConnectionListener#onLogout` callback.
    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](mailto\: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 `ConnectionListener#onLogout` callback. 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 `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](mailto\: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](/en/api-reference/api-ref/im/user-system-registration#forcing-a-user-offline).

    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](mailto\: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](mailto\: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 [#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 friend or group 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 [#prerequisites]

    Before starting this procedure, initialize and connect the SDK to the server. See [SDK quickstart](../../get-started-sdk) for details.

    ## Implement multi-device login [#implement-multi-device-login]

    ### Get the login ID list of other logged-in devices of the current user [#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.

    ```java
    // A synchronous method that will block the current thread. The asynchronous method is asyncGetSelfIdsOnOtherPlatform(ValueCallBack).
    List ids = ChatClient.getInstance().contactManager().getSelfIdsOnOtherPlatform();
    // Select a login ID as the message recipient.
    String toChatUserId = ids.get(0);
    // Create a text message, content is the message text, toChatUserId passes in the login ID as the message recipient.
    ChatMessage message = ChatMessage.createTextSendMessage(content, toChatUserId);
    // Send a message.
    ChatClient.getInstance().chatManager().sendMessage(message);
    ```

    ### Get the list of online logged-in devices for the specified account [#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.

    ```java
        try {
            List deviceInfos = ChatClient.getInstance().getLoggedInDevicesFromServerWithToken(userId, token);
        } catch (HyphenateException e) {
            e.printStackTrace();
        }
    ```

    ### Force the specified account to log out from a single device [#force-the-specified-account-to-log-out-from-a-single-device]

    Call `kickDeviceWithToken` 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 `ChatClient#getLoggedInDevicesFromServerWithToken` and `DeviceInfo#getResource` methods. The logged-out device will receive the `ConnectionListener#onLogout` event.

    <CalloutContainer type="info">
      <CalloutDescription>
        You can also use this interface without logging in.
      </CalloutDescription>
    </CalloutContainer>

    ```java
    // userId: User ID, token: User token. Need to be executed in an asynchronous thread.
    List deviceInfos = ChatClient.getInstance().getLoggedInDevicesFromServerWithToken(userId, token);
    // userId: User ID, token: User token, resource: Device ID. Need to be executed in an asynchronous thread.
    ChatClient.getInstance().kickDeviceWithToken(userId, token, deviceInfos.get(selectedIndex).getResource());
    ```

    ### Force the specified account to log out from all devices [#force-the-specified-account-to-log-out-from-all-devices]

    Call `kickAllDevicesWithToken` 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 `ConnectionListener#onLogout` event.

    <CalloutContainer type="info">
      <CalloutDescription>
        You can also use this interface without logging in.
      </CalloutDescription>
    </CalloutContainer>

    ```java
        try {
            ChatClient.getInstance().kickAllDevicesWithToken(userId,token);
        } catch (HyphenateException e) {
            e.printStackTrace();
        }
    ```

    ### Get operations on other devices [#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 `MultiDeviceListener` class to listen to operations on other devices, and then call the `addMultiDeviceListener` method to add multi-device listening.

    ```java
    //Implement `MultiDeviceListener` to listen to operations on other devices.
    private class ChatMultiDeviceListener implements MultiDeviceListener {
    //@param event event.
        @Override
        //@param target friend's user ID; @param ext event extended information.
        public void onContactEvent(int event, String target, String ext) {
            EMLog.i(TAG, "onContactEvent event"+event);
            String message = null;
            switch (event) {
                //The current user deletes friends on other devices.
                case CONTACT_REMOVE:
                break;
                //The current user accepts friend requests on other devices.
                case CONTACT_ACCEPT:
                break;
                //The current user rejects friend requests on other devices.
                case CONTACT_DECLINE:
                break;
                //The current user adds a user to the blocklist on other devices.
                case CONTACT_BAN:
                break;
                //The current user removes a user from the blocklist on other devices.
                case CONTACT_ALLOW:
                break;
                default:
                break;
            }
        }

        @Override
        public void onGroupEvent(int event, String groupId, List userIds) {
            EMLog.i(TAG, "onGroupEvent event"+event);
            switch (event) {
                //The current user created a group on another device.
                case GROUP_CREATE:
                break;
                //The current user destroyed a group on another device.
                case GROUP_DESTROY:
                break;
                //The current user joined a group on another device.
                case GROUP_JOIN:
                break;
                //The current user left a group on another device.
                case GROUP_LEAVE:
                break;
                //The current user initiated a group application on another device.
                case GROUP_APPLY:
                break;
                //The current user approved the group application on another device.
                case GROUP_APPLY_ACCEPT:
                break;
                //The current user rejected the group application on another device.
                case GROUP_APPLY_DECLINE:
                break;
                //The current user invited group members on other devices.
                case GROUP_INVITE:
                break;
                //The current user accepted the invitation to join the group on other devices.
                case GROUP_INVITE_ACCEPT:
                break;
                //The current user rejected the invitation to join the group on other devices.
                case GROUP_INVITE_DECLINE:
                break;
                //The current user kicked members out of the group on other devices.
                case GROUP_KICK:
                break;
                //The current user added members to the group blocklist on other devices.
                case GROUP_BAN:
                break;
                //The current user removed members from the group blocklist on other devices.
                case GROUP_ALLOW:
                break;
                //The current user blocked the group on other devices.
                case GROUP_BLOCK:
                break;
                //The current user unblocked the group on other devices.
                case GROUP_UNBLOCK:
                break;
                //The current user transferred group ownership on other devices.
                case GROUP_ASSIGN_OWNER:
                break;
                //The current user adds an administrator on other devices.
                case GROUP_ADD_ADMIN:
                break;
                //The current user removes the administrator on other devices.
                case GROUP_REMOVE_ADMIN:
                break;
                //The current user mutes users on other devices.
                case GROUP_ADD_MUTE:
                break;
                //The current user removes the muting on other devices.
                case GROUP_REMOVE_MUTE:
                break;
                //The current user sets custom attributes for group members on other devices.
                case GROUP_METADATA_CHANGED:
                break;
                default:
                break;
            }
        }

        @Override
        public void onChatThreadEvent(int event, String target, List userIds) {
            EMLog.i(TAG, "onChatThreadEvent event"+event);
            switch (event) {
                case THREAD_CREATE:
                //The current user creates a message thread on other devices.
                break;
                case THREAD_DESTROY:
                //The current user destroys the message thread on other devices.
                break;
                case THREAD_JOIN:
                //The current user joins the message thread on other devices.
                break;
                case THREAD_LEAVE:
                //The current user leaves the message thread on other devices.
                break;
                case THREAD_UPDATE:
                //The current user updates the message thread on other devices.
                break;
                case THREAD_KICK:
                //The current user kicks a member out of the message thread on other devices.
                break;
                default:
                break;

            }
        }

        @Override
        public void onConversationEvent(int event, String conversationId, Conversation.ConversationType type) {
            EMLog.i(TAG, "onConversationEvent event"+event);
            switch (event) {
                case CONVERSATION_PINNED:
                //The current user pins a conversation on other devices.
                break;
                case CONVERSATION_UNPINNED:
                //The current user unpins a conversation on other devices.
                break;
                case CONVERSATION_DELETED:
                //The current user deletes a conversation on other devices.
                break;
                case CONVERSATION_MARK_UPDATE:
                //The current user updates the conversation tag on other devices, including adding and removing conversation tags.
                break;
                default:
                break;
            }
        }

        @Override
        public void onMessageRemoved(String conversationId, String deviceId) {
            EMLog.i(TAG, "onMessageRemoved conversationId "+conversationId);
            //The current user unidirectionally deletes message history of a conversation on other devices from the server.
        }
    }

    ChatMultiDeviceListener chatMultiDeviceListener = new ChatMultiDeviceListener();

    //Add a multi-device listener.
    ChatClient.getInstance().addMultiDeviceListener(chatMultiDeviceListener);

    //Remove a multi-device listener.
    ChatClient.getInstance().removeMultiDeviceListener(chatMultiDeviceListener);
    ```

    
  
      
  
      
  
      
  
      
  
      
  
      
  
