In this tutorial, we will be using React Native to build our Android application. React Native let's you build mobile apps using only JavaScript. It uses the same design as React, letting you compose a rich mobile UI from declarative components. To learn more about React Native, please visit here.
First, we need to install the React Native CLI if we don't already have it. To install React Native, we run:
npm install -g react-native-cli
After installing the CLI, it's time to create our project. Open up a terminal, and create a new project called pubchat
using the following command:
react-native init pubchat
We wait until React Native does all its installations, then we can change directory into the new project and run the application using the following command:
1//change directory to pubchat 2cd pubchat 3//run the application 4react-native run-android
Please note, that before running the run-android
command, you should have an emulator running, or an android device connected via adb
.
You can read more on setting up React Native Android app from https://facebook.github.io/react-native/docs/android-setup.html
At this point, we should see this kind of screen:
However, you may run into an error like this:
To fix the error, all you need to do is to run this command:
react-native start
At this point, React Native is ready and set up. We need to setup Pusher, as well as grab our app credentials.
We need to sign up on Pusher and create a new app, and also copy our secret, application key and application id.
We then need to install the required libraries:
npm install native-base pusher-js pusher express body-parser --save
In the above bash command, we installed 4 packages. I will explain what the four packages do below:
After installing these packages, we need to link them with React Native, so we run the following command:
react-native link
**Please note that because we will be using Fetch to perform AJAX request, we would need to go to our android manifest located in android/app/src/AndroidManifest.xml
and add the following permission: **
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
First, let's create a new file called server.js
, which serves as our API in our root folder and place in the following contents into it:
1// server.js 2 3//require express 4var express = require('express') 5//define app as in instance of express 6var app = express() 7//require bosy-parser 8var bodyParser = require('body-parser') 9//require pusher 10var Pusher = require('pusher') 11//use bodyparser as a middle ware 12app.use(bodyParser.json()) 13//instantiate pusher 14const pusher = new Pusher({ 15 appId: 'XXX_APP_ID', 16 key: 'XXX_APP_KEY', 17 secret: 'XXX_APP_SECRET', 18 cluster: 'XXX_APP_CLUSTER', 19 encrypted: true 20}); 21//set cors middleware 22app.use(function(req, res, next) { 23 res.header("Access-Control-Allow-Origin", "*"); 24 res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 25 next(); 26}); 27//handle route postfunction 28app.post('/', function (req, res) { 29 pusher.trigger("pubchat", "message_sent", { message : req.body.message, name : "Anonymous" }); 30 res.send({ 31 message:'message_sent' 32 }); 33}) 34//listen on port and serve the app 35app.listen(3000, function () { 36 console.log('Example app listening on port 3000!') 37})
The code block above is our Express server setup. At the beginning of the file, we had required Express, Body-parser and Pusher libraries for Node.js respectively. We had also initialized a new Pusher object, passing in our appId
, key
, secret
to it, and we set the output of the object to a constant called pusher
.
Next, we set the CORS header to our request, using a middleware function.
Finally, we create a post handler for the \
route, and we then make a Pusher
trigger to a channel called pubchat
with an event called message_sent
.
Let's take note of both the channel name and the event name used on this server. The channel name will be subscribed to, while we will listen for the event in our React Native app.
This is all we need at the server side for our API call to work.
Next, we go to our command line and run:
node server.js
Now let's replace our index.android.js
with the following:
1// index.android.js 2 3/** 4 * Sample React Native App 5 * https://github.com/facebook/react-native 6 * @flow 7 */ 8 9import React, { Component } from 'react'; 10import { 11 AppRegistry, 12 StyleSheet, 13 Text, 14 View, 15 TextInput, 16 ScrollView 17} from 'react-native'; 18// import native base components 19import { Container, Content, Footer, Button} from 'native-base'; 20//import pusher 21import Pusher from 'pusher-js/react-native' 22//react-native class 23export default class pubchat extends Component { 24//load constructor 25constructor(props){ 26 super(props); 27 //declare an array of messages 28 var messages_array = []; 29 // declare initial states 30 this.state ={ 31 messages_array, 32 text:'' 33 } 34 35 //instantiate pusher 36 var pusher = new Pusher('XXX_APP_KEY', { 37 cluster: 'XXX_APP_CLUSTER' 38 }); 39 //subscribe to the public chat channel 40 var my_channel = pusher.subscribe('pubchat'); 41 //bind and listen for chat events 42 my_channel.bind("message_sent", (data)=> { 43 this.state.messages_array.push(data); 44 this.setState({ 45 text:'' 46 }) 47 }); 48} 49 50 //function that sends messahe 51 send_message(){ 52 //check that the text input isnt empty 53 if(this.state.text !=""){ 54 fetch('XXX_IP_TO_MY_ROUTE', { 55 method: 'POST', 56 headers: { 57 'Accept': 'application/json', 58 'Content-Type': 'application/json', 59 }, 60 body: JSON.stringify({ 61 message: this.state.text 62 }) 63 }) 64 .then((response) => response.json()) 65 .then((responseJson) => {}) 66 .catch((error) => { console.error(error); }); 67 } 68 } 69 70 71 //function that loops over our messages and displays them 72 loop(){ 73 var element = []; 74 for (var index = 0; index < this.state.messages_array.length; index++) { 75 76 element.push(<View key={"container"+index} > 77 <Text key = {"author"+index}> 78 {this.state.messages_array[index].name} 79 </Text> 80 <Text key = {index} style={styles.bubble_you} > 81 {this.state.messages_array[index].message} 82 </Text> 83 </View>); 84 } 85 return element; 86 }; 87 88 //render function that actually shows the page 89 render() { 90 //execute the loop function and store its response into a variable 91 myloop = this.loop(); 92 93 return ( 94 <Container> 95 <ScrollView > 96 <View style={styles.container}> 97 <Text style={styles.welcome}> 98 Welcome to the public chat room! 99 </Text> 100 {myloop} 101 </View> 102 </ScrollView> 103 <Footer > 104 <TextInput 105 value ={this.state.text} 106 style={{width: '80%'}} 107 placeholder="Enter Your message!" 108 onChangeText={(text) => this.setState({text})} 109 /> 110 <Button onPress={()=> this.send_message()}> 111 <Text>Send</Text> 112 </Button> 113 </Footer> 114 </Container> 115 ); 116 } 117} 118 119//stylesheet 120const styles = StyleSheet.create({ 121 container: { 122 flex: 1, 123 }, 124 welcome: { 125 fontSize: 20, 126 textAlign: 'center', 127 margin: 10, 128 }, 129 bubble_you: { 130 color: '#fff', 131 backgroundColor: '#00b0ff', 132 width: '50%', 133 borderRadius: 25, 134 padding: 7, 135 marginBottom: 2, 136 }, 137}); 138 139AppRegistry.registerComponent('pubchat', () => pubchat);
Above, we have imported the Native Base component to help us with our UI styling instead of the default React Native components. Next, we imported Pusher for React Native, then we declare our React Native class.
We proceed by creating a constructor, and in our constructor, two states are declared namely: messages_array
and text
, which respectively represent our array of messages as well as the current text that is being typed.
Next, we instantiate Pusher, passing in our APP_KEY
. Then we subscribe to the channel which we are emitting to from the server called pubchat
and also we listen to the message_sent
event which we also trigger from our server.
While listening to the message_sent
event, we push the data that arrives at our messages_array
state, and also set our text
state to empty.
Next, we create a function which sends our messages to the server, so it can be sent to Pusher. In this function, we first check if the state is empty, to avoid sending empty messages to the server.
Next, we use the fetch
API provided by React Native to send an AJAX request to our server which we created earlier.
Note: If you use IP address such as 127.0.0.1
or localhost
, the request is most likely going to fail. This is because, in React Native, localhost
or 127.0.0.1
refers to the internal application. Please use the network IP for your system instead.
Next, we define a loop
function, which loops through all our messages and pushes them into an array which is being returned. This function would be used to display all messages on the UI.
The next function is our render
function, which is a native React Native function. First, we declare a variable called myloop
and set it to our loop
function.
In our return statement, the myloop
variable was rendered, so it can display its content. Also, take a look at the footer
tag we have there. In the footer
tag, we have a text input
and a button
.
The text input text is used to set the text
state anytime the text changes using the onChangeText
event of the button. Notice that our button also calls the send_message
function anytime it is pressed by binding it to its onPress
function.
Finally, we defined some style sheets.
At this point if we reload our application, our app would look like the following:
At this point, once our server is up and running, we should go to the application, type in a message, then send.
Here is a demo of what we have built:
In this article, we have demonstrated how to make a public anonymous chat application in Android using React Native. We have secured the design choices which are important to begin with, and the cases above ought to help you fill in the holes and give an outline of a portion of the other design choices accessible to you.