Introduction: Why implement chat with firebase?
Because it's easier and you can create a working app with one to one chat system in a single day. Let's consider some pros and cons of firebase if we use it as a back end for our chat application.
- Firebase has a realtime database, that means you just need to add appropriate listeners in your app and you will automatically get notified when something is updated in the database.
- It uses json format (key/value pairs) to represent its database which can be user friendly to some of the users who deal with json data on day to day basis.
- It's very fast and manages offline states automatically.
- It also has a authentication system through which you can provide proper login/signup for users.
- No straightforward api available for sending push notification from one device to another (without the use of a separate backend).
- No inbuilt encryption, you would have to implement your own encryption for chatting.
Dependencies required for firebase
Add this line to your project level build.gradle file in dependencies section.
Then, add these to your app level build.gradle file in dependencies section.
Don't forget to apply google services plugin at the end of your app level build.gradle file.
Also, add google-services.json associated with your project to the app module.
Understanding firebase database
Before we get our hands dirty in android studio, we must understand how firebase database is structured so we don't get confused in the later stages.
As you would have guessed by now, firebase database is structured in a json format. So let's suppose we have to save a user's information in firebase, then we will write the data in this format:
We can write this piece of data in our application by first creating a model class for a user which will contain name, age and hobby fields.
Then we can get database reference of firebase and add the object of User class to child "user" to save it in the database.
Now you can easily add data to firebase database, yay! But wait… what if you wanted to add multiple users. In the above scenario the data for “user” will be always replaced instead of maintaining a list. So let's create a list of users.
We can achieve a somewhat similar format by using push() method instead of using setValue(Object object) method. This would generate random keys for your user's object. But this would make it difficult to find a particular user without the knowledge of that random key. So instead, we will add key based on unique uid of user which can be retrieved from FirebaseAuth class.
Now we have learned how to create a single object and a object containing multiple list of similar objects.
Creating appropriate model classes for firebase
Let's create a list of model classes we will be requiring in this project:
Note: Make sure to add an empty constructor to your model classes as sometimes firebase crashes due to the lack of empty constructors.
Creating users for our application
Well we need users for our app, so we need to find a way to add them to our backend. In the application I have created, I add users to the database after they signup using FirebaseAuth. You can skip the authorization part and directly add them to firebase database also. But I would recommend using FirebaseAuth as it would make your life a little bit easier and reduce the development time too.
In order to add a new user, we fill the data in our model class and then add this object to our "users" child using the same method as we used above.
Getting list of users
Now, the next step is to show listing of available users so that we can select one of them and start chatting.
We need to bind a single time listener to the "users" child so that we can get the initial listing of available users.
After retrieving the list of users we can create a chat room through which users will chat with each other.
A chat room will consist of two users in case of one to one chat:
- Currently logged in user.
- User we want to chat with.
For future references let's take two users:
- Kartik (logged in user)
- Kajal (other user Kartik wants to chat with)
Now, we can create a child named "chat_rooms" in our database which will contain all of the data regarding chats between multiple users. We can further create a child of object “chat_rooms” like “Kartik_Kajal” or “Kajal_Kartik”. The reason behind this naming is to make the searching of chat rooms much easier on application's end. You can also use any sort of unique separator instead of underscore, just make sure that it doesn’t conflict with your usernames.
Also, if Kartik is chatting with Kajal for the first time, a room with name “Kartik_Kajal” will be created otherwise if the case is reversed then “Kajal_Kartik” will be created.
We can get list of chat messages by adding a listener to either “Kartik_Kajal” or “Kajal_Kartik” depending upon which one exists. In order to check which one exists we can use method hasChild on “chat_rooms” object.
The above listener will give callbacks on every new chat message added to the firebase database inside the “Kartik_Kajal” chatroom.
Sending push notifications to users
If you want to send a push notification to a particular user, we would have to use firebase push notifications api.
Before that make sure that you have generated a firebase token (using fcm aka firebase cloud messaging) for your user and saved it in your users table in firebase for every individual user.
After you have integrated the code to generate a firebase token, then we can test sample notifications by manually hitting the api in postman.
Now, we can hit the same api using any rest client on our device with custom data object (containing extra information that you would like to send with you push notification). I have used okhttp for managing the api calls, but feel free to use any rest client as per your requirements.
Now you can easily create a one to one chatting system with inbuilt push notifications without the need of an extra backend, yay!
You can also check my chat app on github for further references.