Build and Deploy a Mobile Messaging App with Cordova and Android

Ayooluwa I.
Ayooluwa I.
Published April 13, 2020 Updated June 9, 2021

Apache Cordova is an application development framework that allows you to develop cross-platform apps using web technologies such as HTML, CSS, and JavaScript. Its main advantage over traditional app development workflows is that it allows for the use of a single codebase for Android, iOS, and the browser, which significantly reduces the time and cost needed for the development of a product.

In this tutorial, we’ll go over how you can use the Stream Messaging API to quickly develop a chat application with React and deploy it to an Android device.

Prerequisites

Make sure you have the following installed on your machine:

Additionally, it would help to have a basic familiarity with building React and Node.js applications.

Installing Android Studio

Android Studio is the IDE for creating native Android apps; it includes the Android SDK, which is needed to build our Cordova app for the Android platform. Android Studio can also be used to create virtual devices, which is required if you want to use the Android emulator to test your app. Otherwise, you can deploy your app directly to a test device, as we will be doing in this tutorial.

Once you have Android Studio installed, launch it, and follow the setup instructions to install the Android SDK; make sure to also take note of the SDK location:

Android SDK Setup

Once the Chat SDK has been installed, set the ANDROID_HOME and ANDROID_SDK_ROOT environmental variables to the location of your Android SDK (which we just grabbed) in your .bashrc or .bash_profile file (or the relevant startup file for your preferred shell):

export ANDROID_SDK_ROOT=$HOME/Android/sdk
export ANDROID_HOME=$HOME/Android/sdk

Finally, modify your PATH variable so that it includes the various command-line tools bundled with the Android SDK:

export PATH=$PATH:$ANDROID_SDK_ROOT/tools/bin
export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools
export PATH=$PATH:$ANDROID_SDK_ROOT/emulator

Installing Cordova

The Cordova CLI runs on Node.js, so it can be installed using yarn or npm:

sh
1
$ yarn global add cordova

OR

sh
1
$ npm install -g cordova

Signing Up for Stream

Follow this link to create a new Stream account, or sign in to your existing Stream account. If you've just signed up, you can use the credentials from the app that's already created for you. If you've logged into an existing accaount, once you’re redirected to the dashboard, create a new app or click in an existing one and take note of the application access key and secret, which will be presented at the bottom of the page:

Stream Chat API Credentials

Creating a New Cordova Project

To begin creating your application, let's set up our Cordova project; instantiate a directory for your Cordova project and cd into it:

sh
1
2
$ mkdir cordova-project $ cd cordova-project

Next, create a new Cordova project with the command below. The first argument to the create command is the directory where your project files will be placed, while the second represents your application package identifier, and the third is the "human-readable" name of your project:

sh
1
$ cordova create stream-chat com.example.stream "Stream Chat"

Once the command finished running, you will have a new stream-chat directory in your project root. This directory will contain a few directories that you should be aware of, even though we won’t be using most of them in this tutorial:

Cordova Project
  • The hooks directory is where you’ll place scripts to be executed at different stages in the application lifecycle, such as before or after building the app.
  • The platforms directory will have, within it, a directory for each platform (Android, iOS, etc.) for which you decide to build your app.
  • The plugins directory is where the Cordova plugins are kept.
  • The www directory is the only directory we’ll be working with in this tutorial; it’s where the HTML, CSS, and JavaScript files that make up our application will be placed.

The workflow for creating our Android messaging app with React will be exactly the same as building it for the browser. We’ll make use of Create React App to bootstrap our React app and develop it as if for the browser. After we test the app in the browser and confirm that it’s working as expected, we'll copy the application files over to the www directory and build them for the Android platform, using the Cordova CLI.

Let's dive in!

Creating a New React Application

Within the cordova-project directory root, run the command below to create a new React application:

sh
1
$ npx create-react-app react-app

Once the command is done, cd into the new react-app directory and run the command below to install Stream's Chat JavaScript SDK and React components, in addition to axios, which is used for making HTTP requests in the browser.

sh
1
$ yarn add stream-chat stream-chat-react axios

Finally, run yarn start to launch the application development server on http://localhost:3000.

Setting Up an Authentication Server

Before we construct the application UI, let’s set up an authentication server so that users who attempt to connect to the room will be authenticated before entering.

Within your react-app directory, run the following command to install all the dependencies we’ll be needing to build an Express server:

Building your own app? Get early access to our Livestream or Video Calling API and launch in days!
sh
1
$ yarn add express dotenv cors body-parser

Next, create a new .env file and add your Stream application key and secret, as shown below:

PORT=5500
STREAM_API_KEY=<your api key>
STREAM_APP_SECRET=<your app secret>

Following that, create a server.js file in the root of your react-app directory, and populate it with the following code:

require('dotenv').config();

const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const { StreamChat } = require('stream-chat');

const app = express();

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// initialize Stream Chat SDK
const serverSideClient = new StreamChat(
  process.env.STREAM_API_KEY,
  process.env.STREAM_APP_SECRET
);

app.post('/join', async (req, res) => {
  const { username } = req.body;
  const token = serverSideClient.createToken(username);
  try {
    await serverSideClient.updateUser(
      {
        id: username,
        name: username,
      },
      token
    );

    const admin = { id: 'admin' };
    const channel = serverSideClient.channel('team', 'general', {
      name: 'General',
      created_by: admin,
    });

    await channel.create();
    await channel.addMembers([username, 'admin']);

    res
      .status(200)
      .json({ user: { username }, token, api_key: process.env.STREAM_API_KEY });
  } catch (err) {
    console.error(err);
    res.status(500);
  }
});

const server = app.listen(process.env.PORT || 5500, () => {
  const { port } = server.address();
  console.log(`Server running on PORT ${port}`);
});

That’s all the code we need to authenticate users when they attempt to connect to our chat app! You can start the server on port 5500 by running node server.js in the terminal.

Exposing Your Server to the Web

It’s necessary to expose your local Express server to the web so that it will be possible for your Android app to access it. Once the Express API is available via the web, your Android app will access its endpoints for various actions such as user creation, auth, and more!

Assuming you have Ngrok installed, start an HTTP tunnel on port 5500 by running the following command in a new terminal session (tab/window):

sh
1
$ ./ngrok http 5500

A successful connection will look something like this:

ngrok

Building the Application Interface

We’ll be making use of Stream’s React components to set up our application UI; doing so helps us build out a feature-rich chat interface in a matter of minutes, not days. As a bonus, it’s fully mobile responsive, so it works well for our use case!

Within your react-app directory, open up your src/App.js file in your text editor, and replace its contents with the following code:

import React, { useState, useEffect } from 'react';
import { Chat, Channel, ChannelHeader, Thread, Window, ChannelList, ChannelListTeam, MessageList, MessageTeam, MessageInput, } from 'stream-chat-react';
import { StreamChat } from 'stream-chat';
import rug from 'random-username-generator';
import axios from 'axios';

import 'stream-chat-react/dist/css/index.css';

let chatClient;

function App() {
  const [channel, setChannel] = useState(null);

  useEffect(() => {
    const username = rug.generate();
    async function getToken() {
      try {
        const response = await axios.post('<YOUR_NGROK_URL>/join', {
          username,
        });
        const { token } = response.data;
        const apiKey = response.data.api_key;

        chatClient = new StreamChat(apiKey);

        await chatClient.setUser(
          {
            id: username,
            name: username,
          },
          token
        );

        const channel = chatClient.channel('team', 'general');
        await channel.watch();
        setChannel(channel);
      } catch (err) {
        console.log(err);
        return;
      }
    }

    getToken();
  }, []);

  if (channel) {
    return (
      <Chat client={chatClient} theme="team light">
        <ChannelList
          options={{
            subscribe: true,
            state: true,
          }}
          List={ChannelListTeam}
        />
        <Channel channel={channel}>
          <Window>
            <ChannelHeader />
            <MessageList Message={MessageTeam} />
            <MessageInput focus />
          </Window>
          <Thread Message={MessageTeam} />
        </Channel>
      </Chat>
    );
  }

  return <div>Loading...</div>;
}

export default App;

This is all the code we need to build out our application UI! Try it out in your browser; you should see an interface similar to that in the screenshot below:

Stream Chat Example

Building Your React App for Production

Open up the package.json file in your react-app directory, and update the build script as follows:

json
1
"build": "react-scripts build && rm -r ../stream-chat/www/* && cp -r ./build/* ../stream-chat/www/"

The above script builds your React app and copies the files to the www directory within the stream-chat directory.

You'll also want to set a new homepage property in the package.json file; you can place it before the dependencies property and set the value to "./":

json
1
"homepage": "./"

The above definition preemptively fixes an issue where the Android app fails to load and, thus, displays a blank white screen.

After your package.json file has been updated and saved, run yarn build to build your React app for production.

Building Your Cordova Application for Android

We'll start preparing to deploy our app to Android by setting up and building the Android environment in Cordova. To do this, cd into your stream-chat directory and running the commands below:

sh
1
2
$ cordova platform add android $ cordova build android

This will create an app-debug.apk file, which you can find in your platforms/android/app/build/outputs/apk/debug directory:

Android APK with Cordova

Deploying Your App to Android

This is where the magic happens! Connect your Android device to your computer, and make sure USB debugging is enabled in the Developer options. Next, run the command below to install the application on your device:

sh
1
$ adb install platforms/android/app/build/outputs/apk/debug/app-debug.apk

Now that you've installed the application on your device, find it in your app drawer and launch it; you should see an interface that looks a lot like this:

Mobile View – Android Messaging

Wrapping Up

In this tutorial, we walked through how to get a cross-platform chat application up and running with the help of Cordova, React and Stream. Although we deployed this app to an Android device, it’s also possible to deploy the same codebase to iOS or Electron with minimal effort!

Please refer to the Stream Chat documentation to discover the many additional features that are available on the Stream platform; you can utilize more features from these docs in order to convert this basic app to a production-ready one!

Additionally, if you became lost at any point, or just want to grab the full codebase to use as a starter for a new app, without having to follow along above, you can find the source code used for this tutorial in the GitHub repo.

Thanks for reading, and happy coding!

Integrating Video With Your App?
We've built a Video and Audio solution just for you. Check out our APIs and SDKs.
Learn more ->