Android Tutorial: Chat

Learn our JavaScript SDK by getting your hands dirty.

Introduction

In this tutorial we will use Channels from the Android SDK to create a simple chat app. Channels are real-time communication tools that let apps exchange messages over WebSockets. To keep things simple, we'll skip logins and persistance: this will just be a anonymous public chat room where anyone can participate.

The code for the finished app can be found in the Android SDK's GitHub repo. This tutorial will first describe how you get the app up and running: registering a new account and setting your app key. We will then go through the most important bits of code in the app. Here are a screenshot of the result:

App

Getting started

Download the code

  • Clone or download the Android SDK's GitHub repo.
  • Log in on appstax.com, click on your new app, click on "Settings", and copy your app key.
  • Open Android Studio, select "Import project", and import the examples/appstagram folder.
  • Open app/src/main/java/com/appstax/chatstax/ChatActivity.java and paste in your app key:
public class ChatActivity extends AppCompatActivity {

    protected static final String APPSTAX_KEY = "YourAppKey";

    // ...

}

Running the emulator

You should now be able to run the app in the emulator:

  • In Android Studio, click on the Run app button to start the emulator and run the app.
  • Type messages in the bottom text field to send them to every other user of the app.
  • Launch multiple emulators or install the app on more than one device to test the chat.

We will now go through the most important parts of the code.

Dependencies and permissions

The Appstax Android SDK is avaiable through jcenter, and can be included in the app/build.gradle file:

dependencies {
    // ...
    compile 'com.appstax:appstax-android:+'
}

We also have to set the correct permissions in AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

Creating a channel

Since we're not interested in logging in users or persisting the chat history in this simple example, we won't need to create a new data model. All we need is a public channel that will be used to relay all chat messages.

We instantiate the Appstax SDK with our key, and create a new channel called public/chat.

ax = new Appstax(APPSTAX_KEY);

channel = ax.channel("public/chat").listen(new AxListener() {

    public void onOpen() {
        add(create("Welcome to the chat!"));
    }

    public void onClose() {
        add(create("You lost the connection."));
    }

    public void onMessage(AxEvent event) {
        add(event.getObject());
    }

    public void onError(Exception e) {
        add(create("Something went wrong."));
        e.printStackTrace();
    }

});

Public channels (channels named with the prefix "public/") are open to everyone. Everything after the prefix is up to the developer, and can be used to give your channels distinct names. All channels in your app communicate with the server over a single WebSocket connection.

The callback methods are called as new messages arrive for the current user and channel. The onOpen method gets called when the user has successfully subscribed to the channel. Similarly, the onClose method gets called when this subscription stops. The onError gets called if the connection is interrupted, or if any other error occurs.

The onMessage callback method is the most interesting: it gets called whenever you get a new message on this channel. In this chat app, onMessage is called whenever another user sends a chat message.

Sending messages

When the user types in a new message, we can use the channel to send it to all the other participants:

protected void setListeners() {
    findViewById(R.id.submit).setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            String text = editTextVal(R.id.text);
            clearTextVal(R.id.text);

            if (!text.isEmpty()) {
                AxObject object = create(text);
                channel.send(object);
                add(object);
            }
        }
    });
}

protected AxObject create(String text) {
    AxObject object = ax.object("");
    object.put("date", new Date());
    object.put("text", text);
    return object;
}

The setListeners method is called when the view is created, and adds a listener to the submit button. When the button is clicked, if there is a non-blank message, we create a new AxObject and send it on the channel.

While we could have sent the message as a plain string, we can also send AxObjects across channels. This is helpful whenever we want to send extra details, and not just a simple string in a message.

Displaying messages

Whenever we get a new message on the channel, we call the add method to add it to our view:

protected void add(final AxObject object) {
    runOnUiThread(new Runnable() {
        public void run() {
            items.add(object);
            recyclerAdapter.notifyDataSetChanged();
            recyclerView.scrollToPosition(items.size() - 1);
        }
    });
}

On Android, all mutations on the UI must happen on the main UI thread. Since the callbacks get called from a background thread on demand, we use the standard runOnUiThread Android method to make sure the lit of chat messages get changed on the correct thread. The recyclerAdapter uses our custom ChatAdapter class, which takes care of translating our AxObjects into list items.

Next steps

This has been a very simple example of what you can do with channels. There is much more you can do:

  • You can create private channels and give access to specific users.
  • You can create channels that only you can write to, but everyone can read.
  • You can subscribe to collections to get notified about new or updated objects.

In short, whenever your app requires real-time communication between users, or if you need to know when a collection changes, channels might be just what you need.