Getting Started - Android

Project overview

This quick start will take you through the basics of usingChatkit with Android. At the end of it you will have a working implementation of a 1:1 chat, powered by Chatkit.

You should have some experience with Android development and Kotlin. You will also use some Git as well as Node.js for some additional scripting.
You will need the latest version of Android Studio installed, as well as Git, and Node.JS - 8 or above.

You will build an app with a single chatroom with two users in it - Alice and Bob, who can message each other in realtime. You will learn how to interact with the Chatkit API and connect various features together - such as users, messages and the chatroom itself.

The finished app will look like the one in the animation below.

The app you will be building

Preparation

Installing dependencies

To begin, clone the sample repository using Git:github.com/pusher/chatkit-getting-started-android.
The repository contains two directories - Chatkit-Getting-Started and server. The first one is the Android Studio Project, and the other contains some scripts you can use to create your chatting environment.

Creating a Chatkit instance

First, we need to create a Chatkit instance.

Head on to dash.pusher.com, and click on the Create button in the Chatkit box. Give your instance a name.

name your instance

Clicking the create button will take you to your instance’s dashboard. Click on the Credentials tab under your instance name, where you’ll see 2 long strings - Instance Locator, and Secret Key.
They are unique for each instance. The instance locator lets your app connect to your Chatkit instance, and you will use the Secret Key on the server to authenticate clients. More on that in a bit.

your credentials

Creating users and rooms

Now that you have created and configured a new Chatkit instance, you will learn how to use a Chatkit server SDK to create some users, a chatroom, and populate it with messages.

In the directory that you cloned from GitHub, there is a serversubdirectory. Use your terminal app to cdinto it.

First, run npm install in that directory to install required dependencies. In this case, that’s just the @pusher/chatkit-serverpackage. This is our server SDK for Node.

Next, open the chatkit.js file in your editor, and replace the valuesYOUR_INSTANCE_LOCATOR and YOUR_SECRET_KEY with the instance locator and secret key values from your instance’s dashboard.
This file configures your Chatkit SDK for Node with the correct values, and exports the created Chatkit instance, so that we can re-use it elsewhere with a single import.

Open the create-environment.js file. It is a script that contains a single function create() that will perform the following in your Chatkit instance:

  • Create two users, alice and bob. You will later be able to log in using their user IDs.
  • Create a private room with the ID alice;bob with alice and bob as members of this room.
  • Create a series of messages between the two users in the chatroom created in the previous step.

To run this script, type npm run create-environment in your terminal. The script will let you know what's been successfully created or if there have been any errors that you need to address before moving on.

These are only a few of the operations you can do with Chatkit Node SDK. You can also do most of them using client SDKs, such as the one for Android. The only operation that is exclusive to the server is createUsers. User management is considered an admin operation and is not exposed to clients. You can read more about what’s available for you in the Chatkit Node SDK in the docs.

You’re done with the Node SDK for now, but before moving onto the app part of this guide, lets have a look at another feature of the Chatkit dashboard - the instance inspector.

Using the instance inspector

Go back to your Chatkit dashboard, and select your instance, and click on the Console tab. This is your instance inspector, and is a helpful tool that helps you quickly glance at your Chatkit setup. You can use it to see the users, rooms, messages, and roles. In your case, you should see two users alice and bob who are both members of the room named Alice A, Bob B.

Although the instance inspector lets you perform some of the user actions that you can do with the SDKs, you’ve done it with the Node SDK as it’s more similar to how you would do it in a “real” app.

instance inspector

Developing the app

Running the app

By now you should be familiar with the Chatkit Node SDK, the instance locator, and the dashboard, and have the chatroom set up with two users. You will now integrate Chatkit in your Android application, and see some messages coming through.

We've tried to make this as simple as possible and all the code you need to look at for Chatkit will be contained in theMainActivity.kt file. In addition there is a MessageAdapter.kt andMessageViewHolder.kt which are used to display messages in the RecyclerView. There's also two layout filesactivity_main.xml androw_message.xml which detail the main activities layout, and how each individual message will look.

Open Android Studio, and try running the app. You should be greeted with an empty screen

Instantiating Chatkit

In a more complex app you'd likely abstract out how your app talks to Chatkit, as we're only going to use it in one Activity, we're going to just use it as a class variable.

First, open the file MainActivity.kt. At the top you should see two constants INSTANCE_LOCATORand TOKEN_PROVIDER_URL. Make sure you populate these with your values taken from the credentials tab online. Below this we've also hardcoded our userId, we're going to use this app as Alice.

Next we're going to create our own ChatManager! The chat manager is your initial entry point into Chatkit, and the Current User will be your user’s own context after you've connected to Chatkit. In Chatkit, you will make all API interactions as a user you’re connecting with. This belongs inside the onCreate function.

1
2
3
4
5
6
7
8
9
10
11
val chatManager = ChatManager(
  instanceLocator = INSTANCE_LOCATOR,
  userId = userId,
  dependencies = AndroidChatkitDependencies(
      tokenProvider = ChatkitTokenProvider(
          endpoint = TOKEN_PROVIDER_URL,
          userId = userId
      ),
      context = this
  )
)

Remember to import all the items that flag up red. Android Studio can help you do this if you press Alt + Enter on Windows, or Option + Enter on Mac.

The ChatManager constructor takes 3 arguments:

  • instanceLocator defines which instance it’s connecting to.
  • tokenProvider is the object that fetches valid user tokens.
  • userId is the ID of the Chatkit user that your app will connect as. The user needs to exist in your Chatkit instance before connecting with its ID.

A word on Token Providers

To make any request to the Chatkit API, you will require a valid token, that is signed by your secret key. You will normally generate these tokens in your backend, using the server SDK.
In the client you can use an instance of ChatkitTokenProvider. It takes an endpoint it requests token provides from, and theChatManager will use use these tokens to perform your actions.

For now, we provide you with a Test Token Provider endpoint, that you can enable for testing and development purposes. In a later step you’ll implement a real token provider using the server SDK.

To enable the test token provider, you need to check the box in the dashboard, in the Credentials tab, below the instance locator and the key - as you can see in the screenshot below. The dashboard generates you a Test Token Provider endpoint. Replace the value of url with your newly generated endpoint.

You can read more about how Chatkit performs authentication in the docs.

test token provider inspector

Connecting to Chatkit

Now that you have instantiated your ChatManager, you can use it to connect to the Chatkit service, which will give you the current user when successfully connected:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
chatManager.connect(
    listeners = ChatListeners(),
    callback = { result ->
        when (result) {
            is Result.Success -> {
                result.value.let { user ->
                    currentUser = user

                    //todo: subscribe to a room
                }
            }

            is Error -> {
                Toast.makeText(this, result.reason, Toast.LENGTH_SHORT).show()
            }
        }
    }
)

After you paste this code into your project you're going to need to import all the relevant references. Android Studio will help you import most of them automatically by pressing either Alt + Enter for Windows, or Option + Enter on Mac OS, however there are two that you might need to add yourself:

1
2
import com.pusher.util.Result
import elements.Error

The first parameter for our connect is for listenerswe've just provided an empty object of listeners, however you can find all available options for ChatListeners in the docs. Next we've created a callback that uses a reactive style flow to return when there is a result, we can then check if it that was successful or not.

Subscribing to a room

All rooms your user is a member of are available in theroomsproperty of the connected user. For now, your user only has a single room, so you can get it like this:

1
currentRoom = user.rooms.first()

To subscribe to the room, you need to call the subscribeToRoomMultipartfunction on the current currentUser:

1
2
3
4
5
6
7
currentUser.subscribeToRoomMultipart(
  currentRoom.id,
  RoomListeners(onMultipartMessage = { message ->
    //todo: handle displaying the message
  }),
  messageLimit = 20,
  callback = {})

You need to provide it the id of the room you're interested in subscribing to, an object for optional listeners. You can also provide how many previous messages you'd like to retrieve, and a callback if the subscription was successful - this is useful as it allows you to cancel the subscription later.

Displaying messages

Lastly, as we're using a RecyclerView we've already created you an MessageAdapter. We've created aaddMessage method which allows you to pass in each message as you receive it to be displayed on the screen:

1
2
3
 currentUser.subscribeToRoomMultipart(
  currentRoom.id,
  RoomListeners(onMultipartMessage = { message ->
4
5
6
7
8
   runOnUiThread {
      //add the message to our adapter and scroll to the new message
      adapter.addMessage(message)
      recyclerViewMessages.layoutManager?.scrollToPosition(adapter.messages.size -1)
     }
9
10
11
  }),
  messageLimit = 20,
  callback = {})

Each message has has some useful properties we're using to render it. Firstly we're using the sender property to get the sender name. We're also using the createdAttimestamp to display when the message was sent. To see what other properties are available please check out the docs.

Each message can contain up to 10 different message parts as explained in the core concepts. We're taking the assumption that the first part is always going to be an Inline text element. If you're interested in how this works exactly, take a look at the MessageViewHolder.ktfile to see how we handle this.

Back in the MainActivity.kt, you may have noticed that the logic for dispalying messages is inside a runOnUiThread block. This is because the message handler is running on a background thread, and to display it you need to execute it on the ui thread.

By now you can test receiving messages by opening the app in the simulator and send a test message to your chatroom using the instance inspector in the dashboard.

Sending messages

To send messages from the app yourself, you need to implement thesendMessage method. We've already provided you anEditText with a listener for when the user presses the send message button. All you need to do is add the following code:

  txtMessage.setOnEditorActionListener { v, actionId, event ->
 
      //if the action button was send (replaces the enter button)
      if(actionId == EditorInfo.IME_ACTION_SEND){
 
          //TODO: send message using chatkit
          currentUser.sendSimpleMessage(
              roomId = currentRoom.id,
              messageText = txtMessage.text.toString(),
              callback = {  }
          )
 
          //clear the edit text
          txtMessage.setText("")
 
      }
 
      false
  }

Now you can run the app and send messages!

Extra: Implement the Token Provider

Congratulations! You have successfully implemented Chatkit in an Android app.
If you recall from earlier - we used the Test Token Provider endpoint we enabled in the dashboard.
That’s a great service for testing, but in production is not particularly secure - anyone requesting a token will be granted one for any user ID that they choose.

In practice, you’ll want to issue your own tokens, and tie them to your existing authentication mechanism.

Change your server/server.js to add the following endpoint:

1
2
3
4
5
 const chatkit = require('./chatkit')
 const Express = require('express')
 
 const app = new Express()
 
6
7
8
9
10
11
 app.post("/auth", (req, res) => {
   const authData = chatkit.authenticate({
     userId: req.query.user_id
   })
   res.status(authData.status).send(authData.body)
 })
12
13
14
15
 
 app.listen(3000, () => {
   console.log("Token providing endpoint listening at: http://localhost:3000/auth")
 })

This will listen for POST requests to http://localhost:3000/auth and issue tokens to it.
At the moment this endpoint does not handle any additional security, but you can easily add it by performing a check with your own backend systems before calling chatkit.authenticate(). A common way to authenticate it would be to take the user ID from the session you created in your application when the user logged in.

You can start the server by running npm run serve-token, and replacing thetokenProvider's url field in your app’s to your <your_ip_address>:3000/auth. You might also need to update the AndroidManifest.xmlto allow android:usesCleartextTraffic = true

Note that the localhost URL will only work on a simulated device running on your machine. To test this on a real device, you can use something like Ngrok to create yourself a public URL, or deploy the service to be publicly accessible, for example on Heroku.

Conclusion and next steps

That’s it! You have configured your brand new Chatkit instance and familiarized yourself with the parts that make up Chatkit, including the server and client SDKs, and how authentication works.

You can find the complete project in the same repository, in the complete branch- just replace the instance locator and token provider!

For more detailed information on what else is possible, check out the rest of the docs: