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:
- Node.js v10 or later
- Yarn
- Ngrok
- Android SDK
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:
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
:
1$ yarn global add cordova
OR
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:
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:
12$ 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:
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:
- 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:
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.
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:
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):
1$ ./ngrok http 5500
A successful connection will look something like this:
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:
Building Your React App for Production
Open up the package.json
file in your react-app
directory, and update the build
script as follows:
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 "./
":
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:
12$ 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:
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:
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:
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!