Skip to main content

SDK quickstart

Instant messaging connects people wherever they are and allows them to communicate with others in real time. The Chat SDK enables you to embed real-time messaging in any app, on any device, anywhere.

This page shows a sample code to add peer-to-peer messaging into your app by using the Chat SDK for Android.

Understand the tech

The following figure shows the workflow of how clients send and receive peer-to-peer messages.

understand

As shown in the figure, the workflow of peer-to-peer messaging is as follows:

  1. Clients retrieve a token from your app server.
  2. Client A and Client B log in to Chat.
  3. Client A sends a message to Client B. The message is sent to the Chat server and the server delivers the message to Client B. When Client B receives the message, the SDK triggers an event. Client B listens for the event and gets the message.

Prerequisites

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

  • An Android simulator or a physical Android device.
  • Android Studio 3.6 or higher.
  • Java Development Kit (JDK). You can refer to the User Guide of Android for applicable versions.

Project setup

Follow the steps to create the environment necessary to integrate Chat into your app.

  1. For new projects, in Android Studio, create a Phone and Tablet Android project with an Empty Activity.

    After creating the project, Android Studio automatically starts gradle sync. Ensure that the sync succeeds before you continue.

  2. Integrate the Chat SDK into your project with Maven Central.

    a. In /Gradle Scripts/build.gradle(Project: <projectname>), add the following lines to add the Maven Central dependency:


    _12
    buildscript {
    _12
    repositories {
    _12
    ...
    _12
    mavenCentral()
    _12
    }
    _12
    }
    _12
    allprojects {
    _12
    repositories {
    _12
    ...
    _12
    mavenCentral()
    _12
    }
    _12
    }

    The way to add the Maven Central dependency can be different if you set dependencyResolutionManagement in your Android project.

    b. In /Gradle Scripts/build.gradle(Module: <projectname>.app), add the following lines to integrate the Chat SDK into your Android project:


    _14
    android {
    _14
    defaultConfig {
    _14
    // The Android OS version should be 21 or higher.
    _14
    minSdkVersion 21
    _14
    }
    _14
    compileOptions {
    _14
    sourceCompatibility JavaVersion.VERSION_1_8
    _14
    targetCompatibility JavaVersion.VERSION_1_8
    _14
    }
    _14
    }
    _14
    dependencies {
    _14
    ...
    _14
    implementation 'io.agora.rtc:chat-sdk:X.Y.Z'
    _14
    }

    • minSdkVersion must be 21 or higher for the build process to succeed.
    • For the latest SDK version, go to Sonatype.
  3. Add permissions for network and device access.

    In /app/Manifests/AndroidManifest.xml, add the following permissions after </application>:


    _5
    <uses-permission android:name="android.permission.INTERNET" />
    _5
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    _5
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    _5
    <!—- Need to add after Android 12, apply for alarm clock timing permission -—>
    _5
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

    These are the minimum permissions you need to add to start Chat. You can also add other permissions according to your use case.

  4. Prevent code obfuscation.

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


    _2
    -keep class io.agora.** {*;}
    _2
    -dontwarn io.agora.**

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

Create the UI

  1. To add the text strings used by the UI, open app/res/values/strings.xml and replace the content with the following codes:


    _8
    <resources>
    _8
    <string name="app_name">AgoraChatQuickstart</string>
    _8
    _8
    <string name="app_key">41117440#383391</string>
    _8
    <string name="base_url"><#Developer Token Server#></string>
    _8
    <string name="login_url">%1$s/app/chat/user/login</string>
    _8
    <string name="register_url">%1$s/app/chat/user/register</string>
    _8
    </resources>

    When fetching a token, your token server may differ slightly from our example backend service logic.

    To make this step easier to test, use the temporary token server "https://a41.chat.agora.io" provided by Agora in the placeholder above(Developer Token Server). When you're ready to deploy your own server, swap out your server's URL there, and update any of the POST request logic along with that.

    If you have already got an account and user token, you can ignore this section and go to the next.
  2. To add the UI framework, open app/res/layout/activity_main.xml and replace the content with the following codes:


    _95
    <?xml version="1.0" encoding="utf-8"?>
    _95
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    _95
    xmlns:tools="http://schemas.android.com/tools"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="match_parent"
    _95
    android:orientation="vertical"
    _95
    tools:context="io.agora.agorachatquickstart.MainActivity">
    _95
    _95
    <ScrollView
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="0dp"
    _95
    android:layout_weight="1">
    _95
    _95
    <LinearLayout
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:orientation="vertical"
    _95
    android:gravity="center_horizontal"
    _95
    android:layout_marginStart="20dp"
    _95
    android:layout_marginEnd="20dp">
    _95
    _95
    <EditText
    _95
    android:id="@+id/et_username"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:hint="Enter username"
    _95
    android:layout_marginTop="20dp"/>
    _95
    _95
    <EditText
    _95
    android:id="@+id/et_pwd"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:hint="Enter password"
    _95
    android:inputType="textPassword"
    _95
    android:layout_marginTop="10dp"/>
    _95
    _95
    <Button
    _95
    android:id="@+id/btn_sign_in"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:text="Sign in"
    _95
    android:onClick="signInWithToken"
    _95
    android:layout_marginTop="10dp"/>
    _95
    _95
    <Button
    _95
    android:id="@+id/btn_sign_out"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:text="Sign out"
    _95
    android:onClick="signOut"
    _95
    android:layout_marginTop="10dp"/>
    _95
    _95
    <Button
    _95
    android:id="@+id/btn_sign_up"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:text="Sign up"
    _95
    android:onClick="signUp"
    _95
    android:layout_marginTop="10dp"/>
    _95
    _95
    <EditText
    _95
    android:id="@+id/et_to_chat_name"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:hint="Enter another username"
    _95
    android:layout_marginTop="20dp"/>
    _95
    _95
    <EditText
    _95
    android:id="@+id/et_msg_content"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:hint="Enter content"
    _95
    android:layout_marginTop="10dp"/>
    _95
    _95
    <Button
    _95
    android:id="@+id/btn_send_message"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="wrap_content"
    _95
    android:text="Send message"
    _95
    android:onClick="sendFirstMessage"
    _95
    android:layout_marginTop="20dp"/>
    _95
    _95
    </LinearLayout>
    _95
    _95
    </ScrollView>
    _95
    _95
    <TextView
    _95
    android:id="@+id/tv_log"
    _95
    android:layout_width="match_parent"
    _95
    android:layout_height="200dp"
    _95
    android:hint="Show log area..."
    _95
    android:scrollbars="vertical"
    _95
    android:padding="10dp"/>
    _95
    _95
    </LinearLayout>

Implement the sending and receiving of messages

To enable your app to send and receive messages between individual users, do the following:

  1. Import classes. In app/java/io.agora.agorachatquickstart/MainActivity, add the following lines after import android.os.Bundle; :


    _26
    import static io.agora.cloud.HttpClientManager.Method_POST;
    _26
    import android.text.TextUtils;
    _26
    import android.text.method.ScrollingMovementMethod;
    _26
    import android.view.View;
    _26
    import android.widget.EditText;
    _26
    import android.widget.TextView;
    _26
    import android.widget.Toast;
    _26
    import androidx.annotation.NonNull;
    _26
    import androidx.appcompat.app.AppCompatActivity;
    _26
    import org.json.JSONException;
    _26
    import org.json.JSONObject;
    _26
    import java.text.SimpleDateFormat;
    _26
    import java.util.Date;
    _26
    import java.util.HashMap;
    _26
    import java.util.Locale;
    _26
    import java.util.Map;
    _26
    import io.agora.CallBack;
    _26
    import io.agora.ConnectionListener;
    _26
    import io.agora.Error;
    _26
    import io.agora.ValueCallBack;
    _26
    import io.agora.chat.ChatClient;
    _26
    import io.agora.chat.ChatMessage;
    _26
    import io.agora.chat.ChatOptions;
    _26
    import io.agora.chat.TextMessageBody;
    _26
    import io.agora.cloud.HttpClientManager;
    _26
    import io.agora.cloud.HttpResponse;

  2. Define global variables. In app/java/io.agora.agorachatquickstart/MainActivity, before adding the following lines after AppCompatActivity {, ensure you delete the onCreate function created by default.


    _11
    private EditText et_username;
    _11
    _11
    @Override
    _11
    protected void onCreate(Bundle savedInstanceState) {
    _11
    super.onCreate(savedInstanceState);
    _11
    setContentView(R.layout.activity_main);
    _11
    initView();
    _11
    initSDK();
    _11
    initListener();
    _11
    addConnectionListener();
    _11
    }

  3. Initialize the view and the app. In app/java/io.agora.agorachatquickstart/MainActivity, add the following lines after the onCreate function:


    _22
    // Initializes the view.
    _22
    private void initView() {
    _22
    et_username = findViewById(R.id.et_username);
    _22
    ((TextView) findViewById(R.id.tv_log)).setMovementMethod(new ScrollingMovementMethod());
    _22
    // Initializes the SDK.
    _22
    private void initSDK() {
    _22
    ChatOptions options = new ChatOptions();
    _22
    // Sets your app key applied via Agora Console.
    _22
    String sdkAppkey = getString(R.string.app_key);
    _22
    if (TextUtils.isEmpty(sdkAppkey)) {
    _22
    Toast.makeText(MainActivity.this, "You should set your AppKey first!", Toast.LENGTH_SHORT).show();
    _22
    return;
    _22
    }
    _22
    // Sets your app key to options.
    _22
    options.setAppKey(sdkAppkey);
    _22
    // Set you to use HTTPS only.
    _22
    options.setUsingHttpsOnly(true);
    _22
    // Initializes Chat SDK.
    _22
    ChatClient.getInstance().init(this, options);
    _22
    // Makes the Chat SDK debuggable.
    _22
    ChatClient.getInstance().setDebugMode(true);
    _22
    }

  4. Retrieve a token. To get a token from the app server, add the following lines after the initSDK function:


    _79
    private void getTokenFromAppServer(boolean isRenewToken) {
    _79
    if(ChatClient.getInstance().isLoggedInBefore()) {
    _79
    showLog("An account has been signed in, please sign out first and then sign in", false);
    _79
    return;
    _79
    }
    _79
    String username = et_username.getText().toString().trim();
    _79
    String pwd = ((EditText) findViewById(R.id.et_pwd)).getText().toString().trim();
    _79
    getAgoraTokenFromAppServer(username, pwd, new ValueCallBack<String>() {
    _79
    @Override
    _79
    public void onSuccess(String token) {
    _79
    if(isRenewToken) {
    _79
    ChatClient.getInstance().renewToken(token);
    _79
    }else {
    _79
    login(username,token);
    _79
    }
    _79
    }
    _79
    @Override
    _79
    public void onError(int error, String errorMsg) {
    _79
    showLog(errorMsg, true);
    _79
    }
    _79
    });
    _79
    }
    _79
    // Retrieves a token from the app server.
    _79
    private void getAgoraTokenFromAppServer(String username, String pwd, @NonNull ValueCallBack<String> callBack) {
    _79
    showLog("begin to getTokenFromAppServer ...", false);
    _79
    executeRequest(getString(R.string.login_url, getString(R.string.base_url)), username, pwd, new ValueCallBack<String>() {
    _79
    @Override
    _79
    public void onSuccess(String response) {
    _79
    try {
    _79
    JSONObject object = new JSONObject(response);
    _79
    String token = object.getString("accessToken");
    _79
    callBack.onSuccess(token);
    _79
    } catch (JSONException e) {
    _79
    callBack.onError(Error.GENERAL_ERROR, e.getMessage());
    _79
    }
    _79
    }
    _79
    @Override
    _79
    public void onError(int error, String errorMsg) {
    _79
    callBack.onError(error, errorMsg);
    _79
    }
    _79
    });
    _79
    }
    _79
    private void executeRequest(String url, String username, String password, @NonNull ValueCallBack<String> callBack) {
    _79
    if(TextUtils.isEmpty(url) || TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
    _79
    callBack.onError(Error.INVALID_PARAM, "Request url, username or password should not be empty");
    _79
    return;
    _79
    }
    _79
    Map<String, String> headers = new HashMap<>();
    _79
    headers.put("Content-Type", "application/json");
    _79
    JSONObject request = new JSONObject();
    _79
    try {
    _79
    request.putOpt("userAccount", username);
    _79
    request.putOpt("userPassword", password);
    _79
    } catch (JSONException e) {
    _79
    callBack.onError(Error.GENERAL_ERROR, e.getMessage());
    _79
    return;
    _79
    }
    _79
    execute(()-> {
    _79
    try {
    _79
    HttpResponse response = HttpClientManager.httpExecute(url, headers, request.toString(), Method_POST);
    _79
    int code = response.code;
    _79
    String responseInfo = response.content;
    _79
    if (code == 200) {
    _79
    if (responseInfo != null && responseInfo.length() > 0) {
    _79
    callBack.onSuccess(responseInfo);
    _79
    } else {
    _79
    callBack.onError(Error.SERVER_UNKNOWN_ERROR, responseInfo);
    _79
    }
    _79
    } else {
    _79
    callBack.onError(code, responseInfo);
    _79
    }
    _79
    } catch (Exception e) {
    _79
    callBack.onError(Error.GENERAL_ERROR, e.getMessage());
    _79
    }
    _79
    });
    _79
    }
    _79
    private void execute(Runnable runnable) {
    _79
    new Thread(runnable).start();
    _79
    }

  5. Add event callbacks. In app/java/io.agora.agorachatquickstart/MainActivity, add the following lines after the execute function:


    _43
    private void initListener() {
    _43
    // Add message events callbacks.
    _43
    ChatClient.getInstance().chatManager().addMessageListener(messages -> {
    _43
    for(ChatMessage message : messages) {
    _43
    StringBuilder builder = new StringBuilder();
    _43
    builder.append("Receive a ").append(message.getType().name())
    _43
    .append(" message from: ").append(message.getFrom());
    _43
    if(message.getType() == ChatMessage.Type.TXT) {
    _43
    builder.append(" content:")
    _43
    .append(((TextMessageBody)message.getBody()).getMessage());
    _43
    }
    _43
    showLog(builder.toString(), false);
    _43
    }
    _43
    });
    _43
    // Add connection events callbacks.
    _43
    ChatClient.getInstance().addConnectionListener(new ConnectionListener() {
    _43
    @Override
    _43
    public void onConnected() {
    _43
    showLog("onConnected",false);
    _43
    }
    _43
    @Override
    _43
    public void onDisconnected(int error) {
    _43
    showLog("onDisconnected: "+error,false);
    _43
    }
    _43
    @Override
    _43
    public void onLogout(int errorCode) {
    _43
    showLog("User needs to log out: "+errorCode, false);
    _43
    ChatClient.getInstance().logout(false, null);
    _43
    }
    _43
    // This callback occurs when the token expires. When the callback is triggered, the app client must get a new token from the app server and logs in to the app again.
    _43
    @Override
    _43
    public void onTokenExpired() {
    _43
    showLog("ConnectionListener onTokenExpired", true);
    _43
    signInWithToken(null);
    _43
    }
    _43
    // This callback occurs when the token is to expire.
    _43
    @Override
    _43
    public void onTokenWillExpire() {
    _43
    showLog("ConnectionListener onTokenWillExpire", true);
    _43
    getTokenFromAppServer(true);
    _43
    }
    _43
    });
    _43
    }

  6. Create a user account and log in to the app. To implement this logic, in app/java/io.agora.agorachatquickstart/MainActivity, add the following lines after the initListener function:


    _60
    // Signs up with a username and a password.
    _60
    public void signUp(View view) {
    _60
    String username = et_username.getText().toString().trim();
    _60
    String pwd = ((EditText) findViewById(R.id.et_pwd)).getText().toString().trim();
    _60
    register(username, pwd, new CallBack() {
    _60
    @Override
    _60
    public void onSuccess() {
    _60
    showLog("Sign up success!", true);
    _60
    }
    _60
    @Override
    _60
    public void onError(int code, String error) {
    _60
    showLog(error, true);
    _60
    }
    _60
    });
    _60
    }
    _60
    _60
    // Logs in with the token.
    _60
    public void signInWithToken(View view) {
    _60
    getTokenFromAppServer(false);
    _60
    }
    _60
    _60
    // Signs out.
    _60
    public void signOut(View view) {
    _60
    if(ChatClient.getInstance().isLoggedInBefore()) {
    _60
    ChatClient.getInstance().logout(true, new CallBack() {
    _60
    @Override
    _60
    public void onSuccess() {
    _60
    showLog("Sign out success!", true);
    _60
    }
    _60
    @Override
    _60
    public void onError(int code, String error) {
    _60
    showLog(error, true);
    _60
    }
    _60
    });
    _60
    }
    _60
    }
    _60
    private void register(String username, String pwd, @NonNull CallBack callBack) {
    _60
    showLog("begin to sign up...",false);
    _60
    executeRequest(getString(R.string.register_url, getString(R.string.base_url)), username, pwd, new ValueCallBack<String>() {
    _60
    @Override
    _60
    public void onSuccess(String response) {
    _60
    String resultCode = null;
    _60
    try {
    _60
    JSONObject object = new JSONObject(response);
    _60
    resultCode = object.getString("code");
    _60
    if(resultCode.equals("RES_OK")) {
    _60
    callBack.onSuccess();
    _60
    }else{
    _60
    callBack.onError(Error.GENERAL_ERROR, "Sign up failed!");
    _60
    }
    _60
    } catch (JSONException e) {
    _60
    callBack.onError(Error.GENERAL_ERROR, e.getMessage());
    _60
    }
    _60
    }
    _60
    @Override
    _60
    public void onError(int error, String errorMsg) {
    _60
    callBack.onError(error, errorMsg);
    _60
    }
    _60
    });
    _60
    }

  7. Start a chat. To enable the function of sending messages, add the following lines after the register function:


    _20
    // Sends your first message.
    _20
    public void sendFirstMessage(View view) {
    _20
    String toSendName = ((TextView)findViewById(R.id.et_to_chat_name)).getText().toString().trim();
    _20
    String content = ((TextView)findViewById(R.id.et_msg_content)).getText().toString().trim();
    _20
    // Creates a text message.
    _20
    ChatMessage message = ChatMessage.createTextSendMessage(content, toSendName);
    _20
    // Sets the message callback before sending the message.
    _20
    message.setMessageStatusCallback(new CallBack() {
    _20
    @Override
    _20
    public void onSuccess() {
    _20
    showLog("Send message success!", true);
    _20
    }
    _20
    @Override
    _20
    public void onError(int code, String error) {
    _20
    showLog(error, true);
    _20
    }
    _20
    });
    _20
    // Sends the message.
    _20
    ChatClient.getInstance().chatManager().sendMessage(message);
    _20
    }

  8. Click Sync Project with Gradle Files to sync your project. Now you are ready to test your app.

Test your app

To validate the peer-to-peer messaging you have just integrated into your app using Chat:

  1. In Android Studio, click Run 'app'.

    You see the following interface on your simulator or physical device:

  2. Create a user account and click SIGN UP.

  3. Sign in with the user account you just created and send a message.

  4. Run the app on another Android device or simulator and create another user account. Ensure that the usernames you created are unique.

  5. Send messages between the users.

Next steps

For demonstration purposes, Chat provides an app server that enables you to quickly retrieve a token using the App Key given in this guide. In a production context, the best practice is for you to deploy your own token server, use your own App Key to generate a token, and retrieve the token on the client side to log in to Agora. To see how to implement a server that generates and serves tokens on request, see Generate a User Token.

In addition to integrating the Chat SDK into your project with mavenCentral, you can also manually download the Chat SDK for Android.

  1. Download the latest version of the Chat SDK for Android, and extract the files from the downloaded SDK package.

  2. Copy the following files or subfolders from the libs folder of the downloaded SDK to the corresponding directory of your project.

    File or subfolderPath of your project
    agorachat_X.Y.Z.jar~/app/libs/
    /arm64-v8a/libagora-chat-sdk.so and libsqlite.so~/app/src/main/jniLibs/arm64-v8a/
    /armeabi-v7a/libagora-chat-sdk.so and libsqlite.so~/app/src/main/jniLibs/armeabi-v7a/
    /x86/libagora-chat-sdk.so and libsqlite.so~/app/src/main/jniLibs/x86/
    /x86_64/libagora-chat-sdk.so and libsqlite.so~/app/src/main/jniLibs/x86_64/
    X.Y.Z refers to the version number of the Chat SDK you downloaded.

Reference

For details, see the sample code for getting started with Chat.

Page Content