Chat application in Android Source Code with Example Available

Chat Application in Android Source Code with Example Available. In this tutorial, you’ll learn to build your own Android Chat Application using Android Studio.

Chat application in Android Source Code

We will use a simple ‘Sign In with Google’ and allow the user to create a username and start chatting.

Chat application in Android Source Code

Getting Started

Open Android Studio and create a new Project (AndroidDvlpr Chat App) with an empty activity.

In this project we have to create two activities, one Main Activity that’ll check if the user is signed in and if not then sign up or sign in back. Second, is the Chat activity which will contain an Edittext with a send button and where all chat happens.

Firebase Setup

Chat application in Android Source Code
Chat application in Android Source Code

Create an empty project in Firebase and add your android app to Firebase project. Next, enable Sign in with Google and download and sync google-services.json file with Android Studio.

Learn more about enabling ‘Sign In With Google’ in your Android project from link here.

Adding Libraries

Add the following libraries to your build.gradle (app level) file and sync the project:

implementation 'com.google.firebase:firebase-core:16.0.8'
    implementation 'com.google.firebase:firebase-auth:16.2.1'
    implementation 'com.google.android.gms:play-services-auth:16.0.1'
    implementation 'com.google.firebase:firebase-database:16.1.0'
    implementation 'com.firebaseui:firebase-ui:0.6.2'

Creating Layouts

Sign in Screen (activity_main.xml)

For Sign in Screen we need an Edittext field where user will put a random username and a Google SignInButton for user to sign in to the account.

The XML code for activity_main.xml is as follows:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="@color/colorPrimary">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="156dp"
        android:layout_marginEnd="8dp"
        android:fontFamily="monospace"
        android:text="AndroidDvlpr\nChat Room"
        android:textAlignment="center"
        android:textColor="@color/colorAccent"
        android:textSize="50sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:hint="Enter a random username"
        android:textAlignment="center"
        android:textColor="#FFF"
        android:textColorHint="#7AFFFFFF"
        android:textSize="20sp"
        app:layout_constraintTop_toBottomOf="@id/title"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.496"
        app:layout_constraintStart_toStartOf="parent"
        tools:layout_editor_absoluteY="204dp" />

    <com.google.android.gms.common.SignInButton
        android:id="@+id/signInBtn"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.494"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText" />

</androidx.constraintlayout.widget.ConstraintLayout>

Chat Activity and Chat Bubble Layout (activity_chat.xml)

We need to create a new Blank Activity first to have activity_chat.xml in our project with name ‘ChatActivity‘ as an activity name.

Here is the code for our Chat screen also known as activity_chat.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ChatActivity">

    <ListView
        android:id="@+id/list_message"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="50dp"
        app:layout_constraintBottom_toTopOf="@+id/linearLayout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:stackFromBottom="true"
        android:transcriptMode="alwaysScroll"
        android:dividerHeight="16dp"
        android:divider="@android:color/transparent"
        />

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <EditText
            android:id="@+id/user_message"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_weight="1" />

        <ImageView
            android:id="@+id/send_image"
            android:padding="7dp"
            android:tint="@color/colorAccent"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:layout_weight="5"
            android:src="@drawable/ic_send" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

However, in the chat screen, the chat messages as shown by other users need to appear in a chat bubble, for this we need to create a layout to appear in listView widget.

Create a new Android Layout resource file named list_msg.xml and create layout as follows:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:id="@+id/message_user"
        android:textStyle="normal|bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_alignParentBottom="@+id/message_user"
        android:layout_alignParentEnd="true"
        android:id="@+id/message_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_alignParentStart="true"
        android:layout_marginTop="5dp"
        android:layout_below="@id/message_user"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
        android:textColor="#FFF"
        android:textSize="18sp"
        android:id="@+id/message_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        />

</RelativeLayout>

The code for the ‘Send Button’ which is an android drawable asset can be created by creating a drawable xml file in res/drawable named ic_send.xml. The code for this will be as follows:

<vector android:height="24dp" android:tint="#FFFFFF"
    android:viewportHeight="24.0" android:viewportWidth="24.0"
    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#FF000000" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>

Creating Models

For the signed up users and chat messages, we will need two Model classes in this project i.e, Model_chat (for the chat messages)and Model_User (for the user).

To create Models, right click on the main directory of your app in the java folder (com.androiddvlpr.chatapp) and create a Java Class. (Model_Chat and Model_User)

The code for Model_Chat for chat messages is as follows:

package com.androiddvlpr.chatapp;

public class Model_Chat {

    private String message;
    private String name;
    private Long timestamp;

    public Model_Chat() {
    }

    Model_Chat(String message, String name, Long timestamp) {
        this.message = message;
        this.name = name;
        this.timestamp = timestamp;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
    }
}

The code for Model_User for user registration is as follows:

package com.androiddvlpr.chatapp;

public class Model_User {

    private String username, name, uid, email;
    private Long lastLogin;

    public Model_User() {
    }

    public Model_User(String username, String name, String uid, String email, Long lastLogin) {
        this.username = username;
        this.name = name;
        this.uid = uid;
        this.email = email;
        this.lastLogin = lastLogin;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Long getLastLogin() {
        return lastLogin;
    }

    public void setLastLogin(Long lastLogin) {
        this.lastLogin = lastLogin;
    }
}

Coding the Chat Application in Android Source Code

MainActivity.java

Starting with MainActivity, this is the launcher activity that opens first whenever user opens the app. Here we will check if user is logged in or not and if current user is null (i.e, not logged in) then we will prompt user to sign up before he goes to ChatActivity.class

package com.androiddvlpr.chatapp;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ServerValue;

import java.util.Objects;

public class MainActivity extends AppCompatActivity {

    SignInButton signInButton;
    EditText editText;
    final int RC_SIGN_IN = 123;
    GoogleSignInClient mGoogleSignInClient;
    FirebaseAuth mAuth;
    DatabaseReference mUserDatabase;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        signInButton = findViewById(R.id.signInBtn);
        editText = findViewById(R.id.editText);

        if(editText.getText() != null){
            signIn();
        } else {
            Toast.makeText(MainActivity.this,"Username needed",Toast.LENGTH_SHORT).show();
        }

        // [START config_signin]
        // Configure Google Sign In
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();

        // [END config_signin]

        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

        // [START initialize_auth]
        // Initialize Firebase Auth
        mAuth = FirebaseAuth.getInstance();
        // [END initialize_auth]

    }

    private void signIn() {
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
            try {
                // Google Sign In was successful, authenticate with Firebase
                GoogleSignInAccount account = task.getResult(ApiException.class);
                assert account != null;
                firebaseAuthWithGoogle(account,editText.getText().toString());
            } catch (ApiException e) {
                // Google Sign In failed, update UI appropriately
                //Log.w(TAG, "Google sign in failed", e);
                // ...
            }
        }
    }

    private void firebaseAuthWithGoogle(GoogleSignInAccount acct, final String username) {
       //Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());

        AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            //Log.d(TAG, "signInWithCredential:success");
                            FirebaseUser user = mAuth.getCurrentUser();
                            mUserDatabase = FirebaseDatabase.getInstance().getReference().child("users");
                            assert user != null;
                            mUserDatabase.child(Objects.requireNonNull(mAuth.getUid())).setValue(new Model_User(username,user.getDisplayName(),mAuth.getUid(),user.getEmail(), System.currentTimeMillis()));
                            updateUI(user);
                        } else {
                            // If sign in fails, display a message to the user.
                            //Log.w(TAG, "signInWithCredential:failure", task.getException());
                            Toast.makeText(MainActivity.this, "Authentication Failed.", Toast.LENGTH_SHORT).show();
                            updateUI(null);
                        }

                        // ...
                    }
                });
    }

    void updateUI(FirebaseUser user){
        if(user != null){
            Intent intent = new Intent(MainActivity.this, ChatActivity.class);
            startActivity(intent);
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        mAuth = FirebaseAuth.getInstance();
        // Check if user is signed in (non-null) and update UI accordingly.
        FirebaseUser currentUser = mAuth.getCurrentUser();
        updateUI(currentUser);
    }
}

ChatActivity.java

Once the user has successfully signed in, we will now allow user to initiate chat. In the ChatActivity.class we will not only load chat messages but also check, once user prompts to send a message it should not be blank.

Here is the code for ChatActivity.class:

package com.androiddvlpr.chatapp;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.firebase.ui.database.FirebaseListAdapter;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.Objects;

public class ChatActivity extends AppCompatActivity {

    ImageView sendImage;
    EditText userMessage;
    FirebaseAuth mAuth;
    DatabaseReference mChatData, mUserData;
    String username = "null";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);

        mAuth = FirebaseAuth.getInstance();

        sendImage = findViewById(R.id.send_image);
        userMessage = findViewById(R.id.user_message);

        mChatData = FirebaseDatabase.getInstance().getReference().child("chats");
        mUserData = FirebaseDatabase.getInstance().getReference().child(Objects.requireNonNull(mAuth.getUid()));

        displayChatMessage();

        mUserData.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                username = Objects.requireNonNull(dataSnapshot.child("username").getValue()).toString();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        sendImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(userMessage.getText() != null){
                    if(!userMessage.getText().toString().equals("") && username != null){
                        mChatData.push().setValue(new Model_Chat(userMessage.getText().toString(),username,System.currentTimeMillis()));
                    }
                }
            }
        });

    }

    private void displayChatMessage() {

        ListView listOfMessage = findViewById(R.id.list_message);
        FirebaseListAdapter<Model_Chat> adapter = new FirebaseListAdapter<Model_Chat>(this, Model_Chat.class, R.layout.list_msg, FirebaseDatabase.getInstance().getReference().child("chats").limitToLast(100)) {
            @Override
            protected void populateView(View v, Model_Chat model, int position) {

                TextView messageText, messageUser, messageTime;
                messageText = v.findViewById(R.id.message_text);
                messageUser = v.findViewById(R.id.message_user);
                messageTime = v.findViewById(R.id.message_time);

                messageText.setText(model.getMessage());
                messageUser.setText(model.getName());
                messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)", model.getTimestamp()));

            }
        };
        listOfMessage.setAdapter(adapter);
    }


}

Using FirebaseUI, we have created the Chat messages adapter to display chat messages, while send button checks that the user doesn’t sends a blank message.

Here is the direct link for complete Chat application Source Code.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.