Building an Android Chat Application with Kotlin using QuickBlox SDK

Egor Pavlov
Egor Pavlov
19 May 2020

First Glance

Kotlin is a relatively young language, but it is quickly gaining popularity among developers due to its convenience and modern approach to programming Android apps. Although it is still in development, Kotlin is already considered a mature ecosystem, offering important benefits in Android app development. In this article, we will work on everything you need for building an Android messenger app powered by QuickBlox.
Let’s go!

To start off with the QuickBlox SDK, you need to go through a simple registration following this link

Creating a New Application in the Admin Panel

Now that you have an account with QuickBlox, you can proceed to the next preliminary step.

Create an application in the QuickBlox admin panel. QuickBlox application is a separate space to store your data, users, dialogs, future chat histories, custom objects, and more. To do this, simply click the “+” button.

Add a new app

Next step is to enter a brief description of the chat app:

Admin panel

As you can see on this screen, Title and Type are two required fields.
Title is the name of the application that will be displayed in the QuickBlox admin panel.

Type is the type of your application.
Please note that there can be more than one application inside your admin panel. It is recommended that you create a new QuickBlox application for every new project.

Click the “Add” button at the bottom of the page and the browser will redirect you to the screen with the application already created.

Accessing Credentials In the Admin Panel of the Application

At this point, we should see the following:

Dashboard

Next we will need the Application ID, Authorization key, Authorization secret, and below – the Account key. All these are required for the following authentication of the client-side application using QuickBlox API.

1. Connecting Quickblox Android SDK

To connect QuickBlox SDK to your app, import QuickBlox SDK dependencies via “build.gradle” file (Module: app):

The next step is to synchronize the project with Gradle files. To do this, click the appropriate button inside Android Studio – “Sync Project with Gradle Files”.

After successful synchronization of the project, the previously added dependencies will allow you to interact with the Quickblox Android SDK.

2. Quickblox Android SDK Initialization in the Application

First, we start by creating a new class which extends android.app.Application as follows:

Note that this class must be registered in AndroidManifest.xml. Specify the android:name property in the the node in AndroidManifest.xml:

Also, since we have just signed up, we do not have our own Chat and API servers (these are only available on the Enterprise plan), so there is no need to call the method QBSettings.getInstance().setEndpoints() and QBSettings.getInstance().zone = The Chat and API Domain values obtained will automatically be set.

We have created a library for this purpose, which contains claim type constants (APPLICATION_ID, AUTH_KEY, ...) to use them both in the server and the client projects. Please note that these are your Application ID, Authorization key, Authorization secret and Account key “that you can find in the newly created application (step 0)”

Please be careful, while copying and pasting them into the value of the corresponding constants.

Note! The QBSettings.getInstance().init method must be called before we initialize Activities or Fragments. Which is why we had to create a class file that extends android.app.Application.

After the initialization, a user authorization procedure can be performed.

3.User Authorization

Let’s say we have created a screen, which we correspondingly called LoginActivity, where the application user can input, for example, username, password, and then click the “Login” button to enter the application:

To simplify* we apply user’s authorization with a username and password, but we can just enter an email + password.

*(Or even use the Firebase service for authorization and submit it to the server using the Firebase Project ID and Access Token.)

After the user inputs the username and password, we will need to build the QBUser model for the following authorization and call the method of the QuickBlox Android SDK: QBUsers.signIn(...):

If you correctly added the dependencies to the build.gradle file (application level), all the resources from the QuickBlox Android SDK will be available, as well as the QBUser model and the QBUsers.signIn(...) method that we just used. If the model is not available, it means the dependencies are not connected correctly, or the project is not synchronized.

The code section above shows that when, as a result of the QBUsers.signIn(...) method, the onSuccess callback is invoked, this means that we are successfully logged in the API (as such“user existed”) and now we can log in to the Chat server.

In case something went wrong, the onError callback will be invoked. Also, as it can be seen from the code section above – one of the reasons for this may be that this user has not yet been created and the API returns error 401.

Considering this we will create a new user using QBUsers.signUp(...):

After creating the user (Sign Up), we must log in with the newly created user by calling signIn(...) method again.

To configure a connection to the Chat server is essential before connecting to it:

Now that we are successfully logged in, let’s proceed to authorization to the Chat server:

After successful authorization to the Chat server, we can interact with the API and Chat server.

4. Message List

Before sending messages, you need to download the already existing dialogs: in which our user is listed among occupants:

When dialogs are downloaded successfully, we have got the ArrayList collection, which may be empty if the user doesn’t participate in at least one dialog.

You can save the downloaded dialog collection in any convenient and familiar way, and update as necessary. You will need it when a new dialog is created with the user, or the user was invited to an existing dialog.

It can be saved in an internal database, Shared Preferences, a class that exists while the application is running, or otherwise.

We can now create a dialog with any user that exists in the current QuickBlox application, but to do this you need to download at least several users first.

5. Getting Users from Dialogs

The first thing you can do next is to download and save users who already have dialogs. This must be done in order to get user models from the server and update information about them in our internal storage. Because, since the last update, someone could change their name, phone number, avatar, and other fields.

To download the models of specific users from the server, we can take the dialogs list, get participants from each dialog, create a list from the IDs of these users, and download them from the server. This can be done in the following way:

Here we have initiated a list of unique values from the user IDs that are occupants in each dialog available to us. Then we have created a QBPagedRequestBuilder with the parameters Per page = 100 and page = 1.

Next, when calling the function onSuccess callback (successful download), we check whether we have downloaded all the users, or if we repeat the request by increasing the “page number” by 1.

For example, if we have 146 unique users from the dialogs, our method will work twice. The first time it will load 100 users, then it will call itself again and load the remaining 46.

6. Getting Users by a Specific Parameter

Now let’s download more users from the server, for example, it will be the 100 recently created users from our QuickBlox application:

Please note that in order to create a dialog, you must have at least two users in your QuickBlox application. Users can be created in the admin panel, or by installing the application on several devices, after the registration of a new user (Sign Up).

If QBUsers.getUsers(...) method is performed correctly, the onSuccess() callback will be invoked, which indicates the successful loading of the collection ArrayList. Along with the Dialogs list, you can store it in any convenient and familiar way, and update as necessary.

7. Creating a Dialog

Now that we have some users, we can create a dialog with them.
Before we do this, let’s remember that there are three types of dialogs:

1. Private (QBDialogType.PRIVATE) (when users communicate one-on-one and there is no way to add anyone else to this dialog).

2. Group (QBDialogType.GROUP) (any number of users can participate in the dialog, usually 3 or more. We can also create a group dialog for two users, assuming that we want to add more participants to it).

3. Public (QBDialogType.PUBLIC_GROUP) (All users from your application will be able to join it. The server will create a public chat and return a detailed information about the newly created dialog).

Important! The public dialog model does not contain a list of user IDs. Therefore, the value of publicDialog.occupants an empty list.

Note. You can also create dialogs in the QuickBlox admin panel.

Let’s create a group dialog with any users from the list we have downloaded earlier:

At the beginning, we have created usersIdsList: ArrayList. It is a collection of user IDs with whom we want to create a new dialog. We can create this list, for example, in the following way:

Here usersToCreateDialog is already the list of users with whom we want to create a dialog.

As a result, when onSuccess() callback is triggered, we get the QBChatDialog model of the dialog we just created. It can be added to those already stored, or again request the entire list of dialogs from the server, as we did earlier (QBRestChatService.getChatDialogs(...)).

Note! After receiving a callback about the successful creation of the dialog (onSuccess), we joined the dialog for sending and receiving messages using: qbChatDialog.join(DiscussionHistory()).

Now we are ready to send the first message to the new dialog.

8. Sending a message

Let’s compose a message and send it to the dialog:

Now, if we download the message history of this dialog, our message will appear in it.

9. Loading Chat History

To download the chat history, you should specify the chunk size of messages downloaded from the server (limit), and the number of messages that should be skipped (skip), in case we want the next chunk.

As a result of a successful request to the server, onSuccess() callback works and we get a messages collection: messages: ArrayList.

Just as in the case of downloading Dialogs and Users (QBChatDialog, QBUser) – messages (QBChatMessage) can be stored and updated in any way convenient for you.

Remember when we created the message, we set a parameter“qbChatMessage.setSaveToHistory(true)“?

If the value of this parameter is false, then the message will not be saved on the server, and, accordingly, will not appear in the chat history downloaded from the server.

In the same way, we can load chat history from any dialog available to us.

10. Dialog Message Listener

Almost all the main functionality of our application is now described. Let’s see how to listen to the incoming messages.

All we need is to add a listener (QBChatDialogMessageListener) to the Dialog or listen to all messages, not just from a specific one.

Let’s listen to only one dialog:

We can see, this listener has two callbacks: processMessage and processError. In this case, we need to process events from processMessage. These events will be incoming messages, we will get a QBChatMessage model including all the values of the model fields set by the sender.

– Let’s listen to all the dialogs:

We can use the same listener without a reference to a particular dialog. This is required when we need to receive incoming messages from all dialogs of the user.

11. Messages in the Background

Along with all the other functionality, we need to disconnect from the Chat server when the user sends the application to the background, by minimizing it, or by switching to another application.

As soon as we disconnect from the Chat server, the server understands that we have gone “offline”, and it is necessary to interact with the user in a different way.
Push notifications help to notify the user about any event, whether it is a new incoming message, a new dialog, a “friend” request, and so on.

The main advantage of Push notifications is that they will be received by the device even if our application is not currently running.

Push notifications are worth a separate article, so we’ll talk about them soon. For the scope of this tutorial the most important thing to know is that the Chat server, realizing that we are “offline”, for example, will monitor all messages in Private dialogs and as soon as we appear online (we launch the application, connect to the chat server and become “online” for it), the Chat server will consistently deliver to us messages that were addressed to us during our absence.

To disconnect from the chat server:

And to connect to the Chat server again, as I mentioned above, you need to call (QBChatService.getInstance().login(...)).

12. End a User Session – Logout

Now let’s say we need to sign in as another user, or just log out of the current user’s account in the application

As you can see, after a successful Logout from the API (QBUsers.signOut()), we need to log out from the Chat server, and at the same time clear everything that was connected with the current user session on the Chat server (QBChatService.getInstance().destroy()).

13. Conclusion

Now that we understand how it works, once again let’s go through the entire sequence of logic of the complete chat application, which you will be able to build by following the steps described in this article:

  1. Initialize the QuickBlox SDK
  2. Give the user a possibility to enter username and password (or email and password)
  3. Authorize the user in the API server (create a new one, or sign in as existing)
  4. Configure connection and authorization to the Chat server
  5. Initialize the listener for incoming messages QBChatDialogMessageListener in order to not miss messages.
  6. Download and save to temporary storage the dialogs in which this user participates.
  7. Collect user IDs from existing dialogs (if any) and load users that we “already know”.
  8. If you decide to create a dialog with users that are not yet among the already downloaded ones, load an additional 100 of the last created users, as an example.
  9. Create a new group dialog.
  10. Compose a message and send it to the previously created dialog.
  11. Download the chat history in this dialog, or in any other (if we have a screen displaying the chat history in the dialog, then we need to download the latest chat history every time a user wants to enter the dialog and view his history, or write a new message).
  12. Disconnect from the Chat server when minimizing the application (go to background), and connect to the Chat server when going to foreground.
  13. Logout

More details about how to build a fully functional chat in-app using Kotlin application, how to handle various situations and user behavior in it, how to send and receive push notifications, how to attach photos, audio, video and other types of files to messages, how to use the status delivery of messages and notifications about what your opponent is currently writing to you, as well as much more you can find out by downloading our example from the QuickBlox repo on GitHub.

There are more features available to support more advanced use-cases such as push notifications, content moderation, rich messages, and more. Feel free to contact us if you have any questions.

Please check our official QuickBlox Android documentation for more information.

Share article

Subscribe for news


Thanks for subscribing!

You will receive an email shortly to verify your subscription.

Check out your inbox!

Ready to get started?

QUICKBLOX
post-box
x

Subscribe for news

Get the latest posts and read anywhere.


Don’t forget to visit our social networks:

  • twitter
  • fb
  • linkedin
  • medium
  • git
  • instagram