July 28, 2020

How to build an Android chat app in Java

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 applications are being released each day. There cannot be a better time to learn and build one yourself!


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 Java 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="java" %}
public class RegistrationActivity extends AppCompatActivity {
   private TextInputEditText mobile;
   private TextInputEditText name;
   private MaterialButton createUserBtn;
   private ProgressBar progressBar;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_login);
       progressBar = findViewById(R.id.createUser_pb);
      mobile = findViewById(R.id.etMobile);
       name = findViewById(R.id.etName);
       createUserBtn = findViewById(R.id.create_user_btn);
       createUserBtn.setTextColor(getResources().getColor(R.color.textColorWhite));
       createUserBtn.setOnClickListener(v ->
               signUpTapped()
       );
   }
   private void signUpTapped(){
       User user = new User();
       user.setUid(mobile.getText().toString());
       user.setName(name.getText().toString());
       registerUser(user);
   }
   private void registerUser(User user) {
       progressBar.setVisibility(View.VISIBLE);
       CometChat.createUser(user, AppConfig.AppDetails.API_KEY, new CometChat.CallbackListener<User>() {
           @Override
           public void onSuccess(User user) {
               progressBar.setVisibility(View.GONE);
               login(user);
           }
           @Override
           public void onError(CometChatException e) {
               progressBar.setVisibility(View.GONE);
               createUserBtn.setClickable(true);
              Toast.makeText(RegistrationActivity.this,"Failed to create user",Toast.LENGTH_LONG).show();
           }
       });
   }
   private void login(User user) {
       progressBar.setVisibility(View.VISIBLE);
       CometChat.login(user.getUid(), AppConfig.AppDetails.API_KEY, new CometChat.CallbackListener<User>() {
          @Override
           public void onSuccess(User user) {
               progressBar.setVisibility(View.GONE);
               startActivity(new Intent(RegistrationActivity.this, ConversationsActivity.class));
           }
           @Override
           public void onError(CometChatException e) {
               progressBar.setVisibility(View.GONE);
               Toast.makeText(RegistrationActivity.this,e.getLocalizedMessage(),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 function to accomplish this.

Here’s the code -

{% c-block language="java" %}
public class LoginActivity extends AppCompatActivity {
   private TextInputEditText mobile;
   private MaterialButton loginBtn;
   private MaterialButton signupBtn;
   private ProgressBar progressBar;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_login);
       progressBar = findViewById(R.id.createUser_pb);
       mobile = findViewById(R.id.etMobile);
       signupBtn = findViewById(R.id.create_user_btn);
       loginBtn = findViewById(R.id.login_user_btn);
       loginBtn.setTextColor(getResources().getColor(R.color.textColorWhite));
       loginBtn.setOnClickListener(v ->
               signInTapped()
       );
       signupBtn.setOnClickListener(v ->
               startActivity(new Intent(LoginActivity.this, RegistrationActivity.class))
       );
   }
   private void signInTapped(){
       User user = new User();
       user.setUid(mobile.getText().toString());
       login(user);
   }
   private void login(User user) {
       progressBar.setVisibility(View.VISIBLE);
       CometChat.login(user.getUid(), AppConfig.AppDetails.API_KEY, new CometChat.CallbackListener<User>() {
           @Override
           public void onSuccess(User user) {
               progressBar.setVisibility(View.GONE);
               startActivity(new Intent(LoginActivity.this, ConversationsActivity.class));
           }
           @Override
           public void onError(CometChatException e) {
               progressBar.setVisibility(View.GONE);
           }
       });
   }
}
{% 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="java" %}
public class ConversationsActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       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="java" %}
<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(new OnItemClickListener<Conversation>() {
   @Override
   public void OnItemClick(Conversation var, int position) {
       User user = (User)var.getConversationWith();
       Intent intent = new Intent(ConversationsActivity.this,CometChatMessageScreen.class);
       intent.putExtra(StringContract.IntentStrings.UID, user.getUid());
       intent.putExtra(StringContract.IntentStrings.NAME, user.getName());
       intent.putExtra(StringContract.IntentStrings.AVATAR, user.getAvatar());
       intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.RECEIVER_TYPE_USER);
       startActivity(intent);
   }
   @Override
   public void OnItemLongClick(Conversation var, int position) {
       super.OnItemLongClick(var, position);
   }
});
{% 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.java -  

{% c-block language="java" %}
public class ConversationsActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_conversations);
       CometChatConversationListScreen.setItemClickListener(new OnItemClickListener<Conversation>() {
           @Override
           public void OnItemClick(Conversation var, int position) {
               User user = User.fromJson(var.getConversationWith().toString());
               Intent intent = new Intent(ConversationsActivity.this,CometChatMessageScreen.class);
               intent.putExtra(StringContract.IntentStrings.UID, user.getUid());
               intent.putExtra(StringContract.IntentStrings.NAME, user.getName());
               intent.putExtra(StringContract.IntentStrings.AVATAR, user.getAvatar());
               intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.RECEIVER_TYPE_USER);
               startActivity(intent);
           }
           @Override
           public void OnItemLongClick(Conversation var, int position) {
               super.OnItemLongClick(var, position);
           }
       });
   }
   public void newChatTapped(View view) {
       startActivity(new Intent(ConversationsActivity.this, ContactsActivity.class));
   }
}
{% 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="java" %}
public class ContactsActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       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="java" %}
<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(new OnItemClickListener<User>() {
   @Override
   public void OnItemClick(User var, int position) {
       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);
   }
   @Override
   public void OnItemLongClick(User var, int position) {
       super.OnItemLongClick(var, position);
   }
});
{% 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="java" %}
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