Build a real-time chat app with Firebase: users sign up, sign in, see each other and send messages that appear instantly. A big project that ties together authentication, a cloud database and lists.
A free Firebase project (console.firebase.google.com)
An emulator or an Android phone
How it fits together
1Sign in or create account
2users/{uid}
3Pick a person
4chats/{chatId}/messages
5Both phones update live
Build it step by step
1. Create a Firebase project
In the Firebase console, add an Android app with your package name (com.example.chatapp to copy the code unchanged) and download google-services.json into the app folder.
Realtime Database → Create database. Then open its Rules tab, paste the rules from Required setup, and press Publish. They let only signed-in users see the people list, and only the two people in a chat read it.
3. Add Firebase to the app
In app/build.gradle.kts, add the plugin and dependencies:
A chat's id is the two people's uids in alphabetical order, so both phones open the same chat.
5. Sign in or create an account
LoginActivity uses one screen for both: New here? Create an account shows the name box. createUserWithEmailAndPassword makes the account, then the name and email are saved at users/{uid} so others can find this person. Returning users who are still signed in skip straight to the list.
6. List the people
UsersActivity adds a ValueEventListener to users while the screen is visible. Each time anyone joins, onDataChange gets everyone; leave yourself out and hand the list to UserAdapter.
7. Send a message
In ChatActivity, Send calls messages.push().setValue(...) with the sender, the text and ServerValue.TIMESTAMP. push() creates a key that sorts by time; the server fills in the time, so every phone agrees on the order.
8. Receive messages live
A ChildEventListener calls onChildAdded once for every existing message, then again for each new one. Add it to the adapter and scroll to the bottom. Remove the listener in onDestroy.
9. Draw the bubbles
MessageAdapter has two view types: if you sent the message, use the purple right-hand bubble; otherwise the grey left-hand one. setStackFromEnd(true) starts the list at the newest message.
10. Run it
Run on two emulators (or an emulator and a phone). Create a different account on each, open each other in the list, and chat.
If something goes wrong
"Permission denied": publish the rules from step 2, and make sure you're signed in.
The list is empty: you need a second account; you never see yourself.
Sign-up fails: Email/Password must be enabled, and passwords need at least 6 characters.
What's improved over the video
Sign-in and sign-up share one clean screen, chats use server timestamps, the database rules keep chats private, bubbles follow Material 3, and the message bar stays above the keyboard.
Files affected
Check what to add and what to replace before copying code.
Select a file to see its code and where it belongs.
This code uses package com.example.chatapp. Change that first line to your own package, the one at the top of your MainActivity.
Add these linesapp/src/main/res/layout/activity_chat.xml
Header, messages, and the type-and-send bar.
activity_chat.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".ChatActivity"><!-- Header: back, avatar and name --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="64dp"android:gravity="center_vertical"android:orientation="horizontal"android:paddingHorizontal="8dp"><ImageButtonandroid:id="@+id/btnBack"android:layout_width="48dp"android:layout_height="48dp"android:background="?attr/selectableItemBackgroundBorderless"android:contentDescription="@string/back"android:src="@drawable/ic_back"/><TextViewandroid:id="@+id/textAvatar"style="@style/Avatar"android:layout_marginStart="4dp"tools:text="A"/><TextViewandroid:id="@+id/textName"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_marginStart="12dp"android:layout_weight="1"android:maxLines="1"android:textSize="20sp"android:textStyle="bold"tools:text="Asha"/></LinearLayout><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerMessages"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:clipToPadding="false"android:paddingVertical="8dp"tools:listitem="@layout/item_message_received"/><!-- Type and send --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="bottom"android:orientation="horizontal"android:padding="12dp"><EditTextandroid:id="@+id/inputMessage"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:background="@drawable/input_box"android:hint="@string/hint_message"android:importantForAutofill="no"android:inputType="textMultiLine|textCapSentences"android:maxLines="4"android:minHeight="52dp"android:paddingHorizontal="20dp"android:textSize="17sp"/><ImageButtonandroid:id="@+id/btnSend"android:layout_width="52dp"android:layout_height="52dp"android:layout_marginStart="8dp"android:background="@drawable/circle"android:contentDescription="@string/send"android:src="@drawable/ic_send"/></LinearLayout></LinearLayout>