DEV Community

Cover image for How to Implement Read Receipts On Your Android Chat App?
Alexander Samuel
Alexander Samuel

Posted on

How to Implement Read Receipts On Your Android Chat App?

In this tutorial, you will learn how to implement the read receipt feature on your Android app with the help of MirrorFly SDKs. This entire tutorial is coded in Java, and the steps are illustrated to develop apps in Android Studio.

Please note that this guide assumes that you have a basic familiarity with Javascript. With no further ado, Let’s begin!

Read receipts is a chat app feature that lets senders know when the message they’ve sent is opened or read by the recipient. To implement this feature, you’ll need a ready-to-integrate SDK, which is available to download instantly from MirrorFly.

Let’s take a closer look into the steps to build read receipts into Android apps:

Step 1: Downloading The Chat SDKs

Go to the Signup Page

MirrorFly Register page

  • Sign up using your Google or LinkedIn account or,
  • Fill in the sign up details. An account confirmation link will be sent to your email.
  • Click the link and verify your account.
  • On confirmation, you will be taken to the Account Dashboard
  • From the Overview page, download the Android SDKs
  • Extract the dependencies from the ZIP folder. We’ll use these files in Step 2
  • Next, scroll down to find the License Key
  • You’ll need this License key in Step 3

Step 2: Setting Up The New App Project in Android Studio

Note

This Tutorial uses Android Studio for explanation purposes. However, MirrorFly’s SDKs can be used on any IDEs of your choice to build Android apps.

In this step, we’ll create a New Android App project.

MirrorFly android studio

  1. Open the Android Studio IDE
  2. Fill in the details of your project on the Welcome Page
  3. Select the programming language as Java
  4. The project dashboard will open. On this page, go to the project menu on the left side
  5. Select the App folder
  6. Import all the dependencies downloaded in Step 1

Step 3: Integrating The Chat SDK With The App

Once the dependencies are added to the project,

Add the below code to the build gradle of your app folder
`plugins {
...
id 'kotlin-android'
id 'kotlin-kapt'
}

android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
    jvmTarget = '1.8'
}

packagingOptions {
    exclude 'META-INF/AL2.0'
    exclude 'META-INF/DEPENDENCIES'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/license.txt'
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/notice.txt'
    exclude 'META-INF/ASL2.0'
    exclude 'META-INF/LGPL2.1'
    exclude("META-INF/*.kotlin_module")
}
Enter fullscreen mode Exit fullscreen mode

}
`
Next, add the dependencies to the app/build.gradle file

`dependencies {

 ... // your app dependencies

 implementation files('libs/appbase.aar')
 implementation files('libs/flycommons.aar')
 implementation files('libs/flynetwork.aar')
 implementation files('libs/flydatabase.aar')
 implementation files('libs/videocompression.aar')
 implementation files('libs/xmpp.aar')
Enter fullscreen mode Exit fullscreen mode

}

Add the below modules to the app/build.gradle file

dependencies {

 ... // your app dependencies

 configurations {
     all {
         exclude group: 'org.json', module: 'json'
         exclude group: 'xpp3', module: 'xpp3'
     }
 }

 //For lifecycle listener
 implementation 'android.arch.lifecycle:extensions:1.1.1'
 annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'

 //For GreenDao
 implementation 'de.greenrobot:greendao:2.1.0'

 //For gson parsing
 implementation 'com.google.code.gson:gson:2.8.1'

 //for smack implementation
 implementation 'org.igniterealtime.smack:smack-android:4.4.4'
 implementation 'org.igniterealtime.smack:smack-tcp:4.4.4'
 implementation 'org.igniterealtime.smack:smack-im:4.4.4'
 implementation 'org.igniterealtime.smack:smack-extensions:4.4.4'
 implementation 'org.igniterealtime.smack:smack-sasl-provided:4.4.4'

 implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
 implementation 'androidx.multidex:multidex:2.0.1'
 implementation 'com.google.android.gms:play-services-location:17.0.0'

 //Dagger Dependencies
 api 'com.google.dagger:dagger:2.40.5'
 kapt 'com.google.dagger:dagger-compiler:2.40.5'
 api 'com.google.dagger:dagger-android:2.40.5'
 api 'com.google.dagger:dagger-android-support:2.40.5'
 kapt 'com.google.dagger:dagger-android-processor:2.40.5'

 //coroutines
 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8'
 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.8'

 //apicalls
 implementation 'com.squareup.retrofit2:retrofit:2.6.1'
 implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
 implementation 'com.squareup.okhttp3:okhttp:4.2.0'
 implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'

 //stetho interceptor
 implementation 'com.facebook.stetho:stetho-okhttp3:1.3.1'

 //okhttp interceptor
 implementation 'com.squareup.okhttp3:logging-interceptor:3.14.3'

 //shared preference encryption
 implementation 'androidx.security:security-crypto:1.1.0-alpha03'

 //for mobile number formatting
 implementation 'io.michaelrocks:libphonenumber-android:8.10.1'
Enter fullscreen mode Exit fullscreen mode

}
`

  • In order to refrain from conflict among the imported library files, we’ll need to add the below code to the gradle.properties file.
    android.enableJetifier=true

  • Next, add the permissions to AndroidManifest.xml
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

  • Now, we need to add the License key to the app/build.gradle file
    buildTypes {
    debug {
    buildConfigField 'String', 'SDK_BASE_URL', '"https://api-preprod-sandbox.mirrorfly.com/api/v1/"'
    buildConfigField 'String', 'LICENSE', '"xxxxxxxxxxxxxxxxxxxxxxxxx"'
    buildConfigField 'String', 'WEB_CHAT_LOGIN', '"https://webchat-preprod-sandbox.mirrorfly.com/"'
    buildConfigField "String", "SUPPORT_MAIL", '"contussupport@gmail.com"'
    }
    }

Step 4: Initializing The Chat SDK

This step will collect all the essential data like client and server details to start the data exchange between user devices.

  • To kickstart, add the below code to the onCreate() method of the Application class

`//For chat logging
LogMessage.enableDebugLogging(BuildConfig.DEBUG);

new ChatSDK.Builder()
.setDomainBaseUrl(BuildConfig.SDK_BASE_URL)
.setLicenseKey(BuildConfig.LICENSE)
.setIsTrialLicenceKey(true)
.build();
`

Step 5: Registering The App User

This step is used to register the user in the sandbox or live mode. The below code will check if the license key is on trial and register the user
FlyCore.registerUser(USER_IDENTIFIER, (isSuccess, throwable, data ) -> {
if(isSuccess) {
Boolean isNewUser = (Boolean) data.get("is_new_user");
JSONObject responseObject = (JSONObject) data.get("data");
// Get Username and password from the object
} else {
// Register user failed print throwable to find the exception details.
}
});

Step 6: Connecting To Chat Server

To connect the client-side apps, we’ll need a central server that can execute data exchange between the devices. The below SDK method will set up the server connection and start receiving and sending the data on client requests from user devices.
` ChatManager.connect(new ChatConnectionListener() {
@override
public void onConnected() {
// Write your success logic here to navigate Profile Page or
// To Start your one-one chat with your friends
}

     @Override
     public void onDisconnected() {
        // Connection disconnected
        //No need implementations
     }

    @Override
     public void onConnectionNotAuthorized() {
        // Connection Not authorized
        //No need implementations
    }
});
Enter fullscreen mode Exit fullscreen mode

`

Step 7: Sending Messages

Once, the server connection is established, you can start sending messages from a device through the SDK by implementing the following method

FlyMessenger.sendTextMessage(TO_JID, TEXT, new SendMessageListener() {
@Override
public void onResponse(boolean isSuccess, @Nullable ChatMessage chatMessage) {
// you will get the message sent success response
}
});

Step 8: Receiving Messages

This method will be used to notify the user device when new incoming messages are received on the user device.
@Override
public void onMessageReceived(@NonNull ChatMessage message) {
super.onMessageReceived(message);
// received message object
}

Step 9 : Adding The Read Receipt Feature

Once the app can send and receive messages, the user needs the status of the message delivery on the UI. The below method will notify the user when the recipient has opened the sent message.

Before setting this up, we’ll need to make a few configurations with the user jid. Here are the steps:

  • We’ll need to set the user jid as ongoing chat user in the activity/fragment onResume
    @Override
    public void onResume() {
    super.onResume();
    ChatManager.setOnGoingChatUser(JID);
    }

  • Next, we’ll need to clear the ongoing chat user in the activity/fragment onPause
    @Override
    public void onPause() {
    super.onPause();
    ChatManager.setOnGoingChatUser("");
    }

  • Now, when the chat window is opened, the recipient jid will be passed to the below method

  • The SDK will start using the user jid set by the
    ChatManager.setOnGoingChatUser(jid: String)
    ChatManager.markAsRead(JID)

Step 10: Observing The Message Events

Using the below method, we can register a listener to update the user UI immediately on any message related events. When a message is sent via the SDK, the message status events will give the respective callbacks.
`ChatEventsManager.setupMessageEventListener(new MessageEventsListener() {
@override
public void onMessageReceived(@NotNull ChatMessage message) {
//called when the new message is received
}

        @Override
        public void onMessageStatusUpdated(@NotNull String messageId) {
           //called when the message status is updated
           //find the index of message object in list using messageId
           //then fetch message object from db using `FlyMessenger.getMessageOfId(messageId)` and notify the item in list
        }

        @Override
        public void onMediaStatusUpdated(@NotNull ChatMessage message) {
          //called when the message status is updated
          //find the index of message object in list using messageId
          //then fetch message object from db using `FlyMessenger.getMessageOfId(messageId)` and notify the item in list
        }

        @Override
        public void onUploadDownloadProgressChanged(@NotNull String messageId, int progressPercentage) {
         //called when the media message progress is updated
        }

        @Override
        public void onMessagesClearedOrDeleted(@NotNull ArrayList<String> messageIds) {
         //called when the message is deleted
        }
    });
Enter fullscreen mode Exit fullscreen mode

`

Conclusion

Through this tutorial, we have seen the steps to implement read receipts in an Android chat app, including the respective code samples.

Top comments (0)