July 28, 2020

How to build an Android chat app in Kotlin

Nabil Kazi

Introduction

There is a tremendous increase in chat applications in the market. The current Covid-19 situation worldwide also played its part in this. Many companies are leveraging existing applications to manage their internal communication. We also saw a rise in custom chat applications. More and more communication apps are being released each day. There cannot be a better time to learn and build one yourself!

Many companies and individual developers are transitioning towards Kotlin since Google declared it as the official language. In this tutorial, we would explore the implementation of a chat app in Kotlin based on CometChat UI Kit SDK.

CometChat

If you have never heard of CometChat, the headline on it’s website sums up nicely in one line. Text chat & video calling for your website and apps. It has 2 variants, CometChat Go and CometChat Pro.

  • Go is used for drag and drop chat plugin for your websites and no-code solutions.
  • Pro gives you access to its APIs, SDKs, Components to build your solution with bare minimum development. You can read more about CometChat Pro here.

What we’ll cover in this article?


We’ll be building an Android chat application in Kotlin from scratch. From adding CometChat SDK to live chatting!

Below is the overview of what we’ll be doing -

  • Adding the CometChat SDK and configuring our project.
  • Implementing user registration
  • Setting up conversations & chat screens
  • Live chat in action!

We would be leveraging CometChat’s Android UI Kit to build our chat app. I’ll show you how this makes the development a breeze!

Let’s start building…

Step 1 - Setting up CometChat


Before starting with CometChat, it is important to understand how CometChat works! The Key Concepts page of CometChat documentation can help you with that.

Before diving into the code, we’ll need to setup CometChat in our application. CometChat Quick Start document does a wonderful job explaining the steps in detail.  

We’ll outline the steps from the above document -

  1. Create your CometChat Pro account
  2. Get your Application API Keys
  3. Add the CometChat Dependency in your Application
  4. Add the CometChat Android UI Kit Library
  5. Add Application API Keys, App ID and region and initialize CometChat SDK


Step 2 - Registering / Logging User into our app

CometChat key concepts page states that -

    CometChat does not handle user management. You must handle user registration and login at your end. Once the user is logged into your app/site, you can log in the user to CometChat programmatically. So the user does not ever directly login to CometChat.


It means, in the production environment, you’d either be using your custom back-end application or Firebase for user management. This is where you’d store all the registered users of your app.

So, a typical flow would be →

The user opens your app’s registration page. When the user clicks submit →

  1. You would call your back-end API to register the User in your database.
  2. After a successful response from your API, you would then create the user in CometChat using its createUser() SDK method.

But, for the sake of simplicity, In this tutorial, we would not be using any back-end service or Firebase. We would proceed with the CometChat’s user creation.


Our Registration page asks for User’s name and mobile. We’ll consider Mobile number as the user’s unique identifier - uid.

Now that we have our user’s name and uid, we’ll use CometChat’s createUser()  SDK method to create the user in our CometChat’s database. Then in the final step, we’ll call CometChat’s login()  SDK method to log the user into our app.

You can also view your registered users in the CometChat Dashboard.

Let’s see the entire process in code…

{% c-block language="javascript" %}
class RegistrationActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_register)
       createUserBtn?.setOnClickListener {
           
signUpTapped()
       }
   
}
   private fun signUpTapped() {
       val user = User()
       user.uid = etMobile.text.toString()
       user.name = etName.text.toString()
       registerUser(user)
   }
   private fun registerUser(user: User) {
       progressBar.visibility = View.VISIBLE
       CometChat.createUser(user, AppConfig.AppDetails.API_KEY, object : CometChat.CallbackListener<User>() {
               override fun onSuccess(user: User) {
                   progressBar.visibility = View.GONE
                   login(user)
               }
               override fun onError(e: CometChatException) {
                   progressBar.visibility = View.GONE
                   createUserBtn.isClickable = true
                   Toast.makeText(this@RegistrationActivity, e.localizedMessage, Toast.LENGTH_LONG).show()
               }
           })
   }
   private fun login(user: User) {
       progressBar.visibility = View.VISIBLE
       CometChat.login(user.uid, AppConfig.AppDetails.API_KEY, object : CometChat.CallbackListener<User?>() {
               override fun onSuccess(user: User?) {
                   progressBar.visibility = View.GONE
                   startActivity(Intent(this@RegistrationActivity, ConversationsActivity::class.java))
               }
               override fun onError(e: CometChatException) {
                   progressBar.visibility = View.GONE
                   Toast.makeText(this@RegistrationActivity, e.localizedMessage, Toast.LENGTH_LONG).show()
               }
           })
   }
}
{% c-block-end %}

We’ll also create a Login screen for already registered users. They would be entering their mobile numbers to login. We would use CometChat’s login() SDK method to accomplish this.

Here’s the code -

{% c-block language="javascript" %}
class LoginActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_login)
       loginBtn?.setOnClickListener {
           
signInTapped()
       }
       
signUpBtn?.setOnClickListener {
           
startActivity(Intent(this@LoginActivity, RegistrationActivity::class.java))
       }
   
}
   private fun signInTapped() {
       val user = User()
      user.uid = etMobile.text.toString()
       login(user)
   }
   private fun login(user: User) {
       progressBar.visibility = View.VISIBLE
       CometChat.login(user.uid, AppConfig.AppDetails.API_KEY, object : CometChat.CallbackListener<User?>() {
               override fun onSuccess(user: User?) {
                   progressBar.visibility = View.GONE
                  startActivity(Intent(this@LoginActivity, ConversationsActivity::class.java))
               }
               override fun onError(e: CometChatException) {
                   progressBar.visibility = View.GONE
                   Toast.makeText(this@LoginActivity, e.localizedMessage, Toast.LENGTH_LONG).show()
               }
           })
   }
}
{% c-block-end %}

Note: I have skipped the validation part from the scope of this tutorial. But in a production app, you should add validations on the fields to avoid crashes and unexpected behaviours.

On both the screens, in the Login onSuccess method, I am routing the screen to ConversationsActivity. We’ll be setting this screen up next…


Step 3 - Setting up Conversation List View

Once the user logs in the app, we would be showing the user’s latest conversations. This screen contains a list of all his one-to-one and group conversations.  


For this, we would first create an activity -  ConversationsActivity.  

{% c-block language="javascript" %}
class ConversationsActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_conversations)
   }
}
{% c-block-end %}


In our layout file - activity_conversations.xml, add the following snippet to use the CometChatConversationListScreen. Adding this will give you a fully working list of conversations.

{% c-block language="javascript" %}
<fragment
 android:id="@+id/conversationList"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 class="screen.CometChatConversationListScreen"/>
{% c-block-end %}

CometChatConversationListScreen is a part of CometChat’s Android UI Kit. We won’t have to create RecyclerView, Adapter or any custom development of any sorts to display our conversation list. We won’t even have to call the API ourselves! Whatt???

Yes, CometChat’s UI Kit handles it all for us.

Tapping on any conversation should take the user to its Chat screen. CometChat provides us with an itemClickListener.  Let’s see the implementation -

{% c-block language="java" %}
CometChatConversationListScreen.setItemClickListener(object : OnItemClickListener<Conversation?>() {
   override fun OnItemClick(conversation: Conversation?, position: Int) {
       val user = conversation?.conversationWith.as User
       val intent = Intent(this@ConversationsActivity, CometChatMessageScreen::class.java)
       intent.putExtra(StringContract.IntentStrings.UID, user.uid)
       intent.putExtra(StringContract.IntentStrings.NAME, user.name)
       intent.putExtra(StringContract.IntentStrings.AVATAR, user.avatar)
       intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.RECEIVER_TYPE_USER);
       startActivity(intent)
   }
})
{% c-block-end %}

In the OnItemClick we are routing the user to CometChatMessageScreen. Don’t worry about that activity for now. We’ll see the implementation in the later section of this tutorial.

On our conversations screen, we’ll also want to add a “New Chat” button. This should allow the user to select from an existing list of users. Let’s see our updated code…

ConversationsActivity.kt -

{% c-block language="javascript" %}
class ConversationsActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_conversations)
       CometChatConversationListScreen.setItemClickListener(object : OnItemClickListener<Conversation?>() {
           override fun OnItemClick(conversation: Conversation?, position: Int) {
               val user = User.fromJson(conversation?.conversationWith.toString())
               val intent = Intent(this@ConversationsActivity, CometChatMessageScreen::class.java)
               intent.putExtra(StringContract.IntentStrings.UID, user.uid)
               intent.putExtra(StringContract.IntentStrings.NAME, user.name)
               intent.putExtra(StringContract.IntentStrings.AVATAR, user.avatar)
               intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.RECEIVER_TYPE_USER);
               startActivity(intent)
           }
       })
   }
   fun newChatTapped(view: View?) {
       startActivity(Intent(this@ConversationsActivity, ContactsActivity::class.java))
   }
}
{% c-block-end %}


activity_conversations.xml -


{% c-block language="xml" %}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ConversationsActivity">
   <fragment
       android:id="@+id/conversationList"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       class="screen.CometChatConversationListScreen" />
   <com.google.android.material.floatingactionbutton.FloatingActionButton
       android:id="@+id/fab"
       android:layout_marginEnd="32dp"
       android:layout_marginBottom="32dp"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintBottom_toBottomOf="parent"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:src="@android:drawable/ic_menu_add"
       android:layout_gravity="bottom|end"
       app:elevation="6dp"
       android:onClick="newChatTapped"
       app:pressedTranslationZ="12dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
{% c-block-end %}


In the newChatTapped function, we are routing the screen to ContactsActivity. We’ll be setting this screen up next…

Step 4 - Setting up the User selection screen for New Chat.

Once the user clicks on “New Chat”, we need to display a list of all users of our app.

Let’s see the implementation of ContactsActivity -

{% c-block language="javascript" %}
class ContactsActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_contacts)
   }
}
{% c-block-end %}

In our xml layout file -  activity_contacts.xml, add the following snippet to use the CometChatUserListScreen. Adding this will give you a fully working list of users.

{% c-block language="javascript" %}
<fragment
 android:id="@+id/userList"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 class="screen.CometChatUserListScreen"/>
{% c-block-end %}


CometChatUserListScreen is also a part of CometChat’s Android UI Kit. Like CometChatConversationList,  we won’t have to create RecyclerView, Adapter or any custom development of any sorts to display our user list. We won’t even have to call the API ourselves!

Tapping on any contact should take you to its Chat screen. CometChat provides us with an itemClickListener.  Let’s see the implementation -


{% c-block language="java" %}
CometChatUserListScreen.setItemClickListener(object : OnItemClickListener<User?>() {
   override fun OnItemClick(user: User?, position: Int) {
       val intent = Intent(this@ContactsActivity, CometChatMessageScreen::class.java)
       intent.putExtra(StringContract.IntentStrings.UID, user?.uid)
       intent.putExtra(StringContract.IntentStrings.NAME, user?.name)
       intent.putExtra(StringContract.IntentStrings.AVATAR, user?.avatar)
       intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.RECEIVER_TYPE_USER);
       startActivity(intent)
  }
})
{% c-block-end %}


In the onItemClick we are routing the user to CometChatMessageScreen.

If we recall our earlier implementation of Conversation screen, when the user clicks on an item, we are routing the user to this same screen.

So let’s go ahead and implement the final part of our tutorial- The actual Chat screen!


Step 5 - Implementing the Chat Screen!


Once the user clicks on a Conversation or Contact item, we would route the user to CometChat’s Chat Message screen. We would use CometChatMessageScreen from the CometChat’s Android UI Kit library itself. It displays a list of all the messages, images and the history of entire chat with that person. It is capable of sending and receiving different types of messages such as text, image, and documents.

No UI development needed, no API calls needed! We can get on with our chatting…!

Let’s see its implementation -

Wait! We don’t have to implement this activity separately! We are already calling CometChatMessageScreen from the OnItemClick on Conversations and Contacts activity.

Lets revisit and see what we had implemented earlier -

{% c-block language="javascript" %}
Intent intent = new Intent(ContactsActivity.this, CometChatMessageScreen.class);
intent.putExtra(StringContract.IntentStrings.UID, var.getUid());
intent.putExtra(StringContract.IntentStrings.NAME, var.getName());
intent.putExtra(StringContract.IntentStrings.AVATAR, var.getAvatar());
intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.RECEIVER_TYPE_USER);
startActivity(intent);
{% c-block-end %}

This code routes you to default implementation of CometChat Message Screen. It has all the functionality built-in. No additional code required!

That’s it! You have your working Chat application ready in minutes! Select a user from Conversations Screen or Contacts Screen and start chatting!

You can find the entire source code of this app on GitHub.

Conclusion

CometChat makes it very easy to implement your Chat application. It’s UI Kit gives you predefined screens with all its working. No need to call APIs to fetch the conversations, or chats or users.

If you need more detailed information on CometChat’s Android UI Kit. 3 different ways in which you can leverage it to make a chat app. You can take a look at the official documentation page here.

CometChat caters to your varied needs. Creating a stand-alone chat application or a chat module in your existing app, you name it! You can leave the working of Chat to us and spend more time working on your business logic instead.

Feel free to reach out if you face issues in the implementation or have some quick ideas. I’ll be happy to discuss.