Suggestions

close search

Back to Tutorials

Text Chat Tutorial (Android)

Overview

The OpenTok signaling API allows you to send data between clients connected to an OpenTok session. You can send a signal message to everyone connected to the session, or to a specific client.

In this tutorial, we will use the OpenTok signaling API to implement text chat. You'll start with a completed version of the project, and explore the code that makes it work.

Prerequisites

Step 1: Getting started

The code for this section is available in the Signaling project of the opentok-android-sdk-samples repo. If you haven't already, you'll need to clone the repo into a local directory. On the command line, run:

git clone git@github.com:opentok/opentok-android-sdk-samples.git

Open the Signaling project in Android Studio to follow along.

You'll need to enter in authentication credentials for ApiKey, session ID, and token, in OpenTokConfig.java. You can find these values in your Opentok Dashboard.

Step 2: Text Chat UI

To display our chat messages, we use an android.widget.ListView object. This lets the app display more than one message at a time. We add the following code in the onCreate() method to inflate our layout and obtain references to its views.


setContentView(R.layout.activity_main);

// obtain references to views in your layout file
mMessageEditTextView = (EditText)findViewById(R.id.message_edit_text);
mMessageHistoryListView = (ListView)findViewById(R.id.message_history_list_view);

// Attach data source to our view
mMessageHistory = new SignalMessageAdapter(this);
mMessageHistoryListView.setAdapter(mMessageHistory);

Once we inflate our Android layout views, and attach mMessageHistory to the mMessageHistoryListView, and configure our message editor to send a message when the enter key is pressed on the keyboard.


// Attach handlers to message editor
mMessageEditTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            InputMethodManager inputMethodManager = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
            sendMessage();
            return true;
        }
        return false;
    }
});
mMessageEditTextView.setEnabled(false);

Step 3: Session Initialization

We then obtain your session information and initialize the session, just like in the Basic Video Chat tutorial. Looking at the code, you'll notice that you have the option to either hard code your session info, or use one of our sample server side implementations to obtain it. In either case, you should open the OpenTokConfig.java file and enter in your configuration data.


    ...
    ...

    // initialize the session after validating configs

    // when there is no server URL assiged
    if (OpenTokConfig.CHAT_SERVER_URL == null) {
        // use hard coded session info
        if (OpenTokConfig.areHardCodedConfigsValid()) {
            initializeSession(OpenTokConfig.API_KEY, OpenTokConfig.SESSION_ID, OpenTokConfig.TOKEN);
        } else {
            showConfigError("Configuration Error", OpenTokConfig.hardCodedConfigErrorMessage);
        }
    } else {
        // otherwise initialize WebServiceCoordinator and kick off request for session data
        // session initialization occurs once data is returned, in onSessionConnectionDataReady
        if (OpenTokConfig.isWebServerConfigUrlValid()) {
            mWebServiceCoordinator = new WebServiceCoordinator(this, this);
            mWebServiceCoordinator.fetchSessionConnectionData(OpenTokConfig.SESSION_INFO_ENDPOINT);
        } else {
            showConfigError("Configuration Error", OpenTokConfig.webServerConfigErrorMessage);
        }
    }
}

If you used a server implementation, the session is initialized once your session data is returned. Below are the handler methods for doing this. If you hard coded your session information, you can ignore this.


/* Web Service Coordinator delegate methods */

@Override
public void onSessionConnectionDataReady(String apiKey, String sessionId, String token) {
    Log.d(LOG_TAG, "ApiKey: "+apiKey + " SessionId: "+ sessionId + " Token: "+token);
    initializeSession(apiKey, sessionId, token);
}

@Override
public void onWebServiceCoordinatorError(Exception error) {
    showConfigError("Web Service error", error.getMessage());
}

Step 4: Sending Signals

If you look back to step 2, the sendMessage method is called when the user hits enter on the keyboard. sendMessage creates a SignalMessage object from the visible text in the EditTextView


private void sendMessage() {
    SignalMessage signal = new SignalMessage(mMessageEditTextView.getText().toString());
    mSession.sendSignal(SIGNAL_TYPE, signal.getMessageText());

    mMessageEditTextView.setText("");
}
    

This signal is then sent to all clients connected to the session. sendSignal() is the actual OpenTok method to send a signal. It has two parameters:

We set the type of the signal to SIGNAL_TYPE_CHAT (a string we decided to define as "text-signal"). We'll see later in the onSignalReceived() method, that we checks to see if the signal received is of this type. While in this application, this is our only signal type, you have the flexibility to have multiple different types of signals.

Step 5: Setting the SignalListener

Now we need to set the MainActivity as the SignalListener. In the initializeSession() method of MainActivity.java, we added

mSession.setSignalListener(this);

This sets the MainActivity object as the implementor of the SubscriberKit.SignalListener interface. This interface defines the onSignalReceived(session, type, data, connection) method, which is called when the client receives a signal from the session:

Step 6: Receiving Signals with onSignalReceived

Once MainActivity is set as the SignalListener, it must implement onSignalReceived Here, we first want to differentiate between signals sent from the local Android client and other clients connected to the session. While this check isn't necessary for all applications, our application is a text chat one, and we want to make it clear which messages were sent and which were received.

To do this, we inspect the Connection object. The Connection object in the argument of the method is from the client that the signal was sent from. This will only match the Connection object returned by mSession.getConnection() (which returns the local client's connection) if the signal was sent by the local client. The remote variable is set to true if the signal is coming from a connection that is different than our own, otherwise it is set to false.


@Override
public void onSignalReceived(Session session, String type, String data, Connection connection) {

    boolean remote = !connection.equals(mSession.getConnection());
    if (SIGNAL_TYPE != null && type.equals(SIGNAL_TYPE)) {
        showMessage(data, remote);
    }
}

Next we call the showMessage(messageData, remote) method, passing in remote. Downstream, the SignalMessageAdapter incstance, mMessageHistoryListView will use this to place the view holding the signal's data on the right side of the view if it was being sent, and on the left was being received.


private void showMessage(String messageData, boolean remote) {
    SignalMessage message = new SignalMessage(messageData, remote);
    mMessageHistory.add(message);
}

For more information on the Android classes used in this text chat implementation, see the Android reference docs for the ArrayAdaptor and ListView

Congratulations! You've finished Text Chat Tutorial for Android.
You can continue to play with and adjust the code you've developed here, or check out the Next Steps below. For more information on signaling, see the OpenTok signaling developer guide.