# SDK quickstart (/en/realtime-media/im/get-started-sdk/android)

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

Instant messaging enhances user engagement by enabling users to connect and form a community within the app. Increased engagement can lead to increased user satisfaction and loyalty to your app. An instant messaging feature can also provide real-time support to users, allowing them to get help and answers to their questions quickly. The Chat SDK enables you to embed real-time messaging in any app, on any device, anywhere.

This page guides you through implementing peer-to-peer messaging into your app using the Chat SDK.

## Understand the tech [#understand-the-tech]

The following figure shows the workflow of sending and receiving peer-to-peer messages using Chat SDK.

<details>
  <summary>
    Chat SDK workflow
  </summary>

  ![understand](https://assets-docs.agora.io/images/im/get-started-sdk-understand.png)
</details>

1. Clients retrieve an authentication token from your app server.
2. Users log in to Chat using the App ID, their user ID, and token.
3. Clients send and receive messages through Chat as follows:
   1. Client A sends a message to Client B. The message is sent to the Agora Chat server.
   2. The server delivers the message to Client B. When Client B receives a message, the SDK triggers an event.
   3. Client B listens for the event to read and display the message.

## Prerequisites [#prerequisites]

In order to follow the procedure on this page, you must have:

* A valid [Agora account](/en/realtime-media/im/get-started/manage-agora-account#create-an-agora-account).
* An [Agora project](/en/realtime-media/im/get-started/manage-agora-account#create-an-agora-project) for which you have [enabled Chat](./enable#enable-).
* The [App ID](./enable#get-chat-project-information) for the project.
* Internet access.

  Ensure that no firewall is blocking your network communication.

      
    * An Android emulator or a physical Android device.
    * Android Studio 3.6 or higher.
    * Java Development Kit (JDK). You can refer to the [Android User Guide](https://developer.android.com/studio/write/java8-support) for applicable versions.

    
  
      
  
      
  
      
  
      
  
      
  
      
  
## Project setup [#project-setup]

      
    To integrate Chat into your app, do the following:

    1. Method 1: Use `mavenCentral` to automatically integrate:

       1. In Android Studio, create a new **Phone and Tablet** [Android project](https://developer.android.com/studio/projects/create-project) with an **Empty Activity**. Choose **Java** as the project language, and ensure that the **Minimum SDK** version is set to `21` or higher.

          Android Studio automatically starts gradle sync. Wait for the sync to succeed before you continue.

       2. Add Chat SDK to your project dependencies.

          To add the SDK to your project:

          1. In `/Gradle Scripts/build.gradle (Module: <projectname>.app)`, add the following line under `dependencies`:

             ```text
             dependencies {
                 ...
                 implementation 'io.agora.rtc:chat-sdk:<version>'
             }
             ```

             Replace `<version>` with the version number for the latest Chat SDK release, for example `1.3.1`. You can obtain the latest version information using [Maven Central Repository Search](https://central.sonatype.com/artifact/io.agora.rtc/chat-sdk/versions).

          2. To download the SDK from Maven Central, press **Sync Now**.

       3. Add permissions for network and device access.

          To add the necessary permissions, in `/app/Manifests/AndroidManifest.xml`, add the following permissions after `</application>`:

          ```xml
          <uses-permission android:name="android.permission.INTERNET" />
          <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
          <uses-permission android:name="android.permission.WAKE_LOCK"/>
          <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
          ```

       4. Prevent code obfuscation.

       In `/Gradle Scripts/proguard-rules.pro`, add the following line:

       ```java
       -keep class io.agora.** {*;}
       -dontwarn  io.agora.**
       ```

    2. Method 2: Dynamically load .so library files

       In order to reduce the size of the application installation package, the SDK provides `ChatOptions#setNativeLibBasePath` method to support dynamic loading of the `.so` files required by the SDK. Taking SDK 1.3.0 as an example, the `.so` file includes two files: `libcipherdb.so` and `.libhyphenate.so`. The steps to implement this function are as follows:

       1. Download the latest version of the SDK and unzip it.
       2. Integrate the `agorachat_1.3.0.jar` file into your project.
       3. Upload `.so` files for all schemas to your server and ensure that the application can download `.so` files for the target schemas over the network.
       4. When the application runs, it checks whether the `.so` file exists. If not found, the app downloads the `.so` file and saves it to your custom app's private directory.
       5. When calling `ChatClient#init`, set the app private directory where the `.so` file is located as a parameter into the `ChatOptions#setNativeLibBasePath` method.
       6. The SDK will automatically load `.so` files from the specified path upon initialization.

          ```java
          // Assume that you have put two .so libraries, `libcipherdb.so` and `libagora-chat-sdk.so` in the /data/data/packagename/files directory of the app.
          String filesPath = mContext.getFilesDir().getAbsolutePath();

          ChatOptions options = new ChatOptions();
          options.setNativeLibBasePath(filesPath);

          ChatClient.getInstance().init(mContext, options);
          ```

       <CalloutContainer type="success">
         <CalloutDescription>
           This method is applicable when you integrate the SDK manually but not when you integrate the SDK with Maven Central.

           You can specify the path of `.so` files with the path parameter in the `ChatOptions#setNativeLibBasePath` method. The path must be a valid and private directory of the app.

           If you set this parameter, the SDK will use `System.load` to load the `.so` library from the directory you specify, so that the app dynamically loads the required `.so` files when it runs, thereby reducing the package size.

           If you do not set this parameter or set it to `null`, the SDK will use `System.load` to load the `.so` library from the default path when compiling the app, thus increasing the package size compared to the previous method.

           Since March 6, 2024, using this method to reduce the app size no longer meets the requirements of Google Play. For details, refer to the [Developer Program Policies](https://support.google.com/googleplay/android-developer/answer/14906471?hl=en\&visit_id=638555962315571301-1274648059\&rd=1) issued by Google. If your app needs to be listed on Google Play, please try other ways to reduce the app size. For details, see [App size optimization](/en/realtime-media/rtc/best-practices/app-size-optimization#dynamically-load-so-files).
         </CalloutDescription>
       </CalloutContainer>

    
  
      
  
      
  
      
  
      
  
      
  
      
  
## Implement peer-to-peer messaging [#implement-peer-to-peer-messaging]

This section shows how to use the Chat SDK to implement peer-to-peer messaging in your app, step by step.

      
    ### Create the UI [#create-the-ui]

    In the quickstart app, you create a simple UI that consists of the following elements:

    * A `Button` to log in or out of Agora Chat.
    * An `EditText` box to specify the recipient user ID.
    * An `EditText` box to enter a text message.
    * A `Button` to send the text message.
    * A scrollable layout to display sent and received messages.

    To add the UI framework to your device project, open `app/res/layout/activity_main.xml` and replace the content with the following:

    ```xml
     <?xml version="1.0" encoding="utf-8"?>
     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="#ECE5DD">

         <Button
             android:id="@+id/btnJoinLeave"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_alignParentEnd="true"
             android:layout_alignParentTop="true"
             android:layout_margin="5dp"
             android:onClick="joinLeave"
             android:text="Join" />

         <EditText
             android:id="@+id/etRecipient"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alignBottom="@id/btnJoinLeave"
             android:layout_alignTop="@id/btnJoinLeave"
             android:layout_toStartOf="@id/btnJoinLeave"
             android:layout_margin="5dp"
             android:padding="5dp"
             android:background="#FFFFFF"
             android:hint="Enter recipient user ID" />

         <ScrollView
             android:id="@+id/scrollView"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_above="@id/btnSendMessage"
             android:layout_below="@id/etRecipient"
             android:background="#ECE5DD">

             <LinearLayout
                 android:id="@+id/messageList"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:orientation="vertical">
             </LinearLayout>
         </ScrollView>

         <EditText
             android:id="@+id/etMessageText"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_toStartOf="@id/btnSendMessage"
             android:layout_alignBottom="@id/btnSendMessage"
             android:layout_margin="5dp"
             android:padding="5dp"
             android:background="#FFFFFF"
             android:hint="Message" />

         <Button
             android:id="@+id/btnSendMessage"
             android:layout_width="50dp"
             android:layout_margin="5dp"
             android:layout_height="wrap_content"
             android:layout_alignParentEnd="true"
             android:layout_alignParentBottom="true"
             android:onClick="sendMessage"
             android:text=">>" />
     </RelativeLayout>
    ```

    You see `Cannot resolve symbol` errors in your IDE. This is because this layout refers to methods that you create later.

    ### Handle the system logic [#handle-the-system-logic]

    Import the necessary classes, and add a method to show status updates to the user.

    1. **Import the relevant Agora and Android classes**

       In `/app/java/com.example.<projectname>/MainActivity`, add the following lines after `package com.example.<project name>`:

       ```java
       import android.widget.Button;
       import android.widget.EditText;
       import android.widget.LinearLayout;
       import android.widget.TextView;
       import android.view.View;
       import android.widget.Toast;
       import android.graphics.Color;
       import android.view.Gravity;
       import android.view.inputmethod.InputMethodManager;
       import android.util.Log;
       import java.util.List;

       import io.agora.CallBack;
       import io.agora.ConnectionListener;
       import io.agora.MessageListener;
       import io.agora.chat.ChatClient;
       import io.agora.chat.ChatMessage;
       import io.agora.chat.ChatOptions;
       import io.agora.chat.TextMessageBody;
       ```

    2. **Log events and show status updates to your users**

       In the `MainActivity` class, add the following method before `onCreate`.

       ```javascript
       private void showLog(String text) {
           // Show a toast message
           runOnUiThread(() ->
                   Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show());

           // Write log
           Log.d("AgoraChatQuickStart", text);
       }
       ```

    ### Send and receive messages [#send-and-receive-messages]

    When a user opens the app, you instantiate and initialize a `ChatClient`. When the user taps the **Join** button, the app logs in to Agora Chat. When a user types a message in the text box and then presses **Send**, the typed message is sent to Agora Chat. When the app receives a message from the server, the message is displayed in the message list. This simple workflow enables you to rapidly build a Chat client with basic functionality.

    The following figure shows the API call sequence for implementing this workflow.

    <details>
      <summary>
        API call sequence
      </summary>

      ![image](https://assets-docs.agora.io/images/im/chat-call-logic-android.svg)
    </details>

    To implement this workflow in your app, take the following steps:

    1. **Declare variables**

       In the `MainActivity` class, add the following declarations:

       ```java
       private String userId = "<User ID of the local user>";
       private String token = "<Your authentication token>";
       private String appId = "<App ID from Agora console>";

       private ChatClient agoraChatClient;
       private boolean isJoined = false;
       EditText editMessage;
       ```

    2. **Set up Chat when the app starts**

       When the app starts, you create an instance of the `ChatClient` and set up callbacks to handle Chat events.
       To do this, replace the `onCreate` method in the `MainActivity` class with the following:

       ```java
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);

           setupChatClient(); // Initialize the ChatClient
           setupListeners(); // Add event listeners

           // Set up UI elements for code access
           editMessage = findViewById(R.id.etMessageText);
       }
       ```

    3. **Instantiate the `ChatClient`**

       To implement peer-to-peer messaging, you use Chat SDK to initialize a `ChatClient` instance. In the `MainActivity` class, add the following method before `onCreate`.

       ```java
       private void setupChatClient() {
           ChatOptions options = new ChatOptions();
           if (appId.isEmpty()) {
               showLog("You need to set your App ID");
               return;
           }
           options.setAppId(appId); // Set your app ID in options
           agoraChatClient = ChatClient.getInstance();
           agoraChatClient.init(this, options); // Initialize the ChatClient
           agoraChatClient.setDebugMode(true); // Enable debug info output
       }
       ```

    4. **Handle and respond to Chat events**

       To receive notification of Chat events such as connection, disconnection, and token expiration, you add a `ConnectionListener`. To handle message delivery and new message notifications, you add a `MessageListener`. When you receive the `onMessageReceived` notification, you display the message to the user.

       In `/app/java/com.example.<projectname>/MainActivity`, add the following method after `setupChatClient`:

       ```java
       private void setupListeners() {
           // Add message event callbacks
           agoraChatClient.chatManager().addMessageListener(new MessageListener() {
               @Override
               public void onMessageReceived(List<ChatMessage> messages) {
                   for (ChatMessage message : messages) {
                       runOnUiThread(() ->
                               displayMessage(((TextMessageBody) message.getBody()).getMessage(),
                                       false)
                       );
                       showLog("Received a " + message.getType().name()
                               + " message from " + message.getFrom());
                   }
               }
           });

           // Add connection event callbacks
           agoraChatClient.addConnectionListener(new ConnectionListener() {
               @Override
               public void onConnected() {
                   showLog("Connected");
               }

               @Override
               public void onDisconnected(int error) {
                   if (isJoined) {
                       showLog("Disconnected: " + error);
                       isJoined = false;
                   }
               }

               @Override
               public void onLogout(int errorCode) {
                   showLog("User logging out: " + errorCode);
               }

               @Override
               public void onTokenExpired() {
                   // The token has expired
               }

               @Override
               public void onTokenWillExpire() {
                   // The token is about to expire. Get a new token
                   // from the token server and renew the token.
               }
           });
       }
       ```

    5. **Log in to Agora Chat**

       When a user clicks **Join**, your app logs in to Agora Chat. When a user clicks **Leave**, the app logs out of Agora Chat.

       To implement this logic, in the `MainActivity` class, add the following method before `onCreate`:

       ```java
       public void joinLeave(View view) {
           Button button = findViewById(R.id.btnJoinLeave);

           if (isJoined) {
               agoraChatClient.logout(true, new CallBack() {
                   @Override
                   public void onSuccess() {
                       showLog("Sign out success!");
                       runOnUiThread(() -> button.setText("Join"));
                       isJoined = false;
                   }
                   @Override
                   public void onError(int code, String error) {
                       showLog(error);
                   }
               });
           } else {
               agoraChatClient.loginWithToken(userId, token, new CallBack() {
                   @Override
                   public void onSuccess() {
                       showLog("Signed in");
                       isJoined = true;
                       runOnUiThread(() -> button.setText("Leave"));
                   }
                   @Override
                   public void onError(int code, String error) {
                       if (code == 200) { // Already joined
                           isJoined = true;
                           runOnUiThread(() -> button.setText("Leave"));
                       } else {
                           showLog(error);
                       }
                   }
               });
           }
       }
       ```

    6. **Send a message**

       To send a message to Agora Chat when a user presses the **Send** button, add the following method to the `MainActivity` class, before `onCreate`:

       ```java
       public void sendMessage(View view) {
           // Read the recipient name from the EditText box
           String toSendName = ((EditText) findViewById(R.id.etRecipient)).getText().toString().trim();
           String content = editMessage.getText().toString().trim();

           if (toSendName.isEmpty() || content.isEmpty()) {
               showLog("Enter a recipient name and a message");
               return;
           }

           // Create a ChatMessage
           ChatMessage message = ChatMessage.createTextSendMessage(content, toSendName);

           // Set the message callback before sending the message
           message.setMessageStatusCallback(new CallBack() {
               @Override
               public void onSuccess() {
                   showLog("Message sent");
                   runOnUiThread(() -> {
                       displayMessage(content, true);
                       // Clear the box and hide the keyboard after sending the message
                       editMessage.setText("");
                       InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
                       inputMethodManager.hideSoftInputFromWindow(editMessage.getApplicationWindowToken(),0);
                   });
               }

               @Override
               public void onError(int code, String error) {
                   showLog(error);
               }
           });

           // Send the message
           agoraChatClient.chatManager().sendMessage(message);
       }
       ```

    7. **Display chat messages**

       To display the messages the current user has sent and received in your app, add the following method to the `MainActivity` class:

       ```java
       void displayMessage(String messageText, boolean isSentMessage) {
           // Create a new TextView
           final TextView messageTextView = new TextView(this);
           messageTextView.setText(messageText);
           messageTextView.setPadding(10,10,10,10);

           // Set formatting
           LinearLayout messageList = findViewById(R.id.messageList);
           LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                   LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);

           if (isSentMessage) {
               params.gravity = Gravity.END;
               messageTextView.setBackgroundColor(Color.parseColor("#DCF8C6"));
               params.setMargins(100,25,15,5);
           } else {
               messageTextView.setBackgroundColor(Color.parseColor("white"));
               params.setMargins(15,25,100,5);
           }

           // Add the message TextView to the LinearLayout
           messageList.addView(messageTextView, params);
       }
       ```

    
  
      
  
      
  
      
  
      
  
      
  
      
  
## Test your implementation [#test-your-implementation]

To ensure that you have implemented Peer-to-Peer Messaging in your app:

      
    1. Create an app instance for the first user:

       1. [Register a user](./enable#register-a-user) in [Agora Console](https://console.agora.io/v2) and [Generate a user token](./enable#generate-a-user-token).

       2. In the `MainActivity` class, update `userId`, `token`, and `appId` with values from Agora Console.  To get your App ID, see [Get Chat project information](./enable#get-chat-project-information).

       3. Connect a physical Android device to your development device.

       4. In Android Studio, click **Run app**. A moment later you see the project installed on your device.

    2. Create an app instance for the second user:

       1. Register a second user in Agora Console and generate a user token.

       2. In the `MainActivity` class, update `userId` and `token` with values for the second user. Make sure you use the same `appId` as for the first user.

       3. Run the modified app on a device emulator or a second physical Android device.

    3. On each device, click **Join** to log in to Agora Chat.

    4. Edit the recipient name on each device to show the user ID of the user logged in to the other device.

    5. Type a message in the **Message*&#x2A; box of either device and press &#x2A;*`>>`**.

       The message is sent and appears on the other device.

    6. Press **Leave** to log out of Agora Chat.

    
  
      
  
      
  
      
  
      
  
      
  
      
  
## Reference [#reference]

This section contains content that completes the information in this page, or points you to documentation that explains other aspects to this product.

* For more code samples, see [Samples and demos](./downloads).

      
    * [Manual install](./reference/manual-sdk-install) shows you how to integrate Chat SDK into your project manually.

    ### Integration issues [#integration-issues]

    If your project integrates Agora Chat SDK 1.3.2 or later and either Signaling SDK 2.2.0 or later or Video SDK 4.3.0 or later, you may encounter a compilation error because the `libaosl.so` library is included in both SDKs.

    ```
    com.android.builder.merge.DuplicateRelativeFileException: More than one file was found with OS independent path 'lib/x86/libaosl.so'
    ```

    To resolve this issue, add packaging options under the `Android` node in the `build.gradle` file of your app. This ensures that the build process prioritizes the first matching file:

    <Tabs defaultValue="groovy" groupId="build-script">
      <TabsList>
        <TabsTrigger value="groovy">
          Groovy
        </TabsTrigger>

        <TabsTrigger value="kotlin">
          Kotlin DSL
        </TabsTrigger>
      </TabsList>

      <TabsContent value="groovy">
        * **Android Gradle Plugin \< 7.x**

          ```text
          android {
              packagingOptions {
                  pickFirst 'lib/**/libaosl.so'
              }
          }

          dependencies {
              implementation 'io.agora.infra:aosl:x.y.z'
              // implementation RTM sdk
              // implementation RTC sdk
          }
          ```

        * **Android Gradle Plugin 7.x or later**

          ```text
          android {
              packaging {
                  jniLibs {
                      pickFirsts += ["lib/**/libaosl.so"]
                  }
              }
          }

          dependencies {
              implementation 'io.agora.infra:aosl:x.y.z'
              // implementation RTM sdk
              // implementation RTC sdk
          }
          ```
      </TabsContent>

      <TabsContent value="kotlin">
        * **Android Gradle Plugin \< 7.x**

          ```kotlin
          android {
              packagingOptions {
                  pickFirst("lib/**/libaosl.so")
              }
          }

          dependencies {
              implementation("io.agora.infra:aosl:x.y.z")
              // implementation RTM sdk
              // implementation RTC sdk
          }
          ```

        * **Android Gradle Plugin 7.x or later**

          ```kotlin
          android {
              packaging {
                  jniLibs {
                      pickFirsts += setOf("lib/**/libaosl.so")
                  }
              }
          }

          dependencies {
              implementation("io.agora.infra:aosl:x.y.z")
              // implementation RTM sdk
              // implementation RTC sdk
          }
          ```
      </TabsContent>
    </Tabs>

    ### API reference [#api-reference]

    * [`ChatClient.init()`](https://api-ref.agora.io/en/chat-sdk/android/1.x/classio_1_1agora_1_1chat_1_1_chat_client.html#ab8220f870c05ad326f4de256c5814852)

    * [`ChatClient.loginWithToken()`](https://api-ref.agora.io/en/chat-sdk/android/1.x/classio_1_1agora_1_1chat_1_1_chat_client.html#abb72e1e403e7e3f4ded23e8b4f460bd6)

    * [`ChatClient.logout()`](https://api-ref.agora.io/en/chat-sdk/android/1.x/classio_1_1agora_1_1chat_1_1_chat_client.html#a014e2abb85595417b64799dabfb8ac74)

    * [`ChatManager.sendMessage()`](https://api-ref.agora.io/en/chat-sdk/android/1.x/classio_1_1agora_1_1chat_1_1_chat_manager.html#aed75ce0a590423ac18a94e1d339e97f4)

    * [`ChatManager`](https://api-ref.agora.io/en/chat-sdk/android/1.x/classio_1_1agora_1_1chat_1_1_chat_manager.html)

    * [`ChatMessage`](https://api-ref.agora.io/en/chat-sdk/android/1.x/classio_1_1agora_1_1chat_1_1_chat_message.html)

    * [`ConnectionListener`](https://api-ref.agora.io/en/chat-sdk/android/1.x/interfaceio_1_1agora_1_1_connection_listener.html)

    * [`MessageListener`](https://api-ref.agora.io/en/chat-sdk/android/1.x/interfaceio_1_1agora_1_1_message_listener.html)

    
  
      
  
      
  
      
  
      
  
      
  
      
  
### Next steps [#next-steps]

In a production environment, best practice is to deploy your own token server. Users retrieve a token from the token server to log in to Chat. To see how to implement a server that generates and serves tokens on request, see [Secure authentication with tokens](../develop/authentication).
