How to Implement Chat Functionality in Social Media Android App?

09 May, 2022
This is the Part 14 of “Build a Social Media App on Android Studio” tutorial, and we are going to cover the following functionalities in this article:
We are going to Create a Layout for chat & Send Messages in Chat.
A user can send either a Message or an Image.
A user can send an image either using a camera or gallery.
Firstly a request for permission will be asked to send an image using a gallery or after clicking the image using the camera.
If permission is given then the user can send the image, or it will again request for asking permission.
Step 1: Create two new layout resource files and name them row_chat_left and row_chat_right
Working with the row_chat_left.xml file. The received message will be on the left side. Similarly, Working with the row_chat_right.xml file. The message sends to the user will be on the right side. Below is the code for the row_chat_left.xml file and row_chat_right.xml file.
XML
XML
<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/msglayout"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical"    android:padding="10dp">     <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">         <de.hdodenhof.circleimageview.CircleImageView            android:id="@+id/profilec"            android:layout_width="50dp"            android:layout_height="50dp"            android:src="@drawable/profile_image"            app:civ_border_color="@null" />         <TextView            android:id="@+id/msgc"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="1"            android:background="@drawable/bg_receiver"            android:padding="15dp"            android:text="His Message"            android:textColor="@color/colorBlack"            android:textSize="16sp"            android:visibility="gone" />         <ImageView            android:id="@+id/images"            android:layout_width="200dp"            android:layout_height="200dp"            android:adjustViewBounds="true"            android:background="@drawable/bg_receiver"            android:padding="15dp"            android:scaleType="fitCenter"            android:src="@drawable/ic_images" />         <TextView            android:id="@+id/timetv"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="02/01/1990 06:19PM"            android:textColor="@color/colorBlack"            android:textSize="12sp" />    </LinearLayout>     <TextView        android:id="@+id/isSeen"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="end"        android:text="Delivered"        android:textAlignment="textEnd"        android:visibility="gone" />     </LinearLayout>
<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/msglayout"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical"    android:padding="10dp">     <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">         <de.hdodenhof.circleimageview.CircleImageView            android:id="@+id/profilec"            android:layout_width="50dp"            android:layout_height="50dp"            android:src="@drawable/profile_image"            android:visibility="gone"            app:civ_border_color="@null" />         <TextView            android:id="@+id/timetv"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="02/01/1990 06:19PM"            android:textColor="@color/colorBlack"            android:textSize="12sp" />         <TextView            android:id="@+id/msgc"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentEnd="true"            android:layout_toEndOf="@id/timetv"            android:background="@drawable/bg_sender"            android:padding="15dp"            android:text="His Message"            android:textColor="@color/colorBlack"            android:textSize="16sp" />         <ImageView            android:id="@+id/images"            android:layout_width="200dp"            android:layout_height="200dp"            android:layout_alignParentEnd="true"            android:adjustViewBounds="true"            android:background="@drawable/bg_sender"            android:padding="15dp"            android:scaleType="fitCenter"            android:src="@drawable/ic_images" />     </RelativeLayout>     <TextView        android:id="@+id/isSeen"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="end"        android:text="Delivered"        android:textAlignment="textEnd" />     </LinearLayout>
 Step 2: Working with the activity_chat.xml file 
Here In the RecyclerView, we will be showing all the messages. In the TextView user will type the message and using the send button user will send the message. Below is the code for the activity_chat.xml file. 
XML
<?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"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".ChatActivity">     <androidx.appcompat.widget.Toolbar        android:id="@+id/toolbar"        android:layout_width="match_parent"        android:layout_height="?android:attr/actionBarSize"        android:background="@color/colorPrimaryDark"        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">         <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="horizontal">             <de.hdodenhof.circleimageview.CircleImageView                android:id="@+id/profiletv"                android:layout_width="35dp"                android:layout_height="35dp"                android:scaleType="centerCrop"                android:src="@drawable/profile_image"                app:civ_circle_background_color="@color/colorPrimaryDark" />             <LinearLayout                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_marginStart="20dp"                android:layout_marginLeft="20dp"                android:layout_weight="1"                android:gravity="center"                android:orientation="vertical">                 <TextView                    android:id="@+id/nameptv"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:layout_weight="1"                    android:text="HisName"                    android:textColor="@color/colorWhite"                    android:textSize="18sp"                    android:textStyle="bold" />                 <TextView                    android:id="@+id/onlinetv"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:text="Online"                    android:textColor="@color/colorWhite"                    android:textStyle="bold" />             </LinearLayout>             <ImageView                android:id="@+id/block"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center_vertical"                android:layout_marginEnd="5dp"                android:src="@drawable/ic_unblock" />        </LinearLayout>             </androidx.appcompat.widget.Toolbar>     <androidx.recyclerview.widget.RecyclerView        android:id="@+id/chatrecycle"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_above="@id/chatlayout"        android:layout_below="@id/toolbar" />     <LinearLayout        android:id="@+id/chatlayout"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:background="@color/colorWhite"        android:gravity="center"        android:orientation="horizontal">         <ImageButton            android:id="@+id/attachbtn"            android:layout_width="50dp"            android:layout_height="50dp"            android:background="@null"            android:src="@drawable/ic_iattach" />         <EditText            android:id="@+id/messaget"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:background="@null"            android:hint="Start Typing"            android:inputType="textCapSentences|textMultiLine"            android:padding="15dp" />         <ImageButton            android:id="@+id/sendmsg"            android:layout_width="40dp"            android:layout_height="40dp"            android:background="@null"            android:src="@drawable/send_message" />             </LinearLayout>     </RelativeLayout>
 Step 3: Working with the row_chatlist.xml file
Create another layout resource file and name the file as row_chatlist. Below is the code for the row_chatlist.xml file. 
XML
<?xml version="1.0" encoding="utf-8"?><androidx.cardview.widget.CardView    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="wrap_content"    android:orientation="vertical"    app:contentPadding="3dp">     <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content">         <de.hdodenhof.circleimageview.CircleImageView            android:id="@+id/profileimage"            android:layout_width="70dp"            android:layout_height="70dp"            android:src="@drawable/profile_image" />         <de.hdodenhof.circleimageview.CircleImageView            android:id="@+id/onlinestatus"            android:layout_width="25dp"            android:layout_height="25dp" />         <TextView            android:id="@+id/nameonline"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginStart="4dp"            android:layout_toEndOf="@id/profileimage"            android:layout_toRightOf="@id/profileimage"            android:text="His Name"            android:textColor="@color/colorBlack"            android:textSize="18sp" />         <TextView            android:id="@+id/lastmessge"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_below="@id/nameonline"            android:layout_marginStart="4dp"            android:layout_toEndOf="@id/profileimage"            android:layout_toRightOf="@id/profileimage"            android:maxLines="2"            android:text="Last Message"            android:textColor="@color/colorBlack" />         <ImageView            android:id="@+id/blocking"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentEnd="true"            android:layout_gravity="center_vertical"            android:src="@drawable/ic_unblock" />         <ImageView            android:id="@+id/seen"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_below="@id/blocking"            android:layout_alignParentEnd="true"            android:layout_gravity="center_vertical"            android:src="@drawable/ic_unblock" />             </RelativeLayout> </androidx.cardview.widget.CardView>
 Step 4: Working with the ModelChat.java file 
Created this class to initialize the key so that we can retrieve the value of the key later. 
Java
package com.example.socialmediaapp; public class ModelChat {    String message;      public String getMessage() {        return message;    }     public void setMessage(String message) {        this.message = message;    }     public String getReceiver() {        return receiver;    }     public void setReceiver(String receiver) {        this.receiver = receiver;    }     public String getSender() {        return sender;    }     public void setSender(String sender) {        this.sender = sender;    }     public String getTimestamp() {        return timestamp;    }     public void setTimestamp(String timestamp) {        this.timestamp = timestamp;    }     public boolean isDilihat() {        return dilihat;    }     public void setDilihat(boolean dilihat) {        this.dilihat = dilihat;    }     String receiver;     public ModelChat() {    }     String sender;     public String getType() {        return type;    }     public void setType(String type) {        this.type = type;    }     public ModelChat(String message, String receiver, String sender, String type, String timestamp, boolean dilihat) {        this.message = message;        this.receiver = receiver;        this.sender = sender;        this.type = type;        this.timestamp = timestamp;        this.dilihat = dilihat;    }     String type;      String timestamp;      boolean dilihat;}
 Step 5: Working with the AdpaterChat.java file
Create a new java class and name the class as AdpaterChat. Below is the code for the AdpaterChat.java file. 
Java
package com.example.socialmediaapp; import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.text.format.DateFormat;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import android.widget.Toast; import androidx.annotation.NonNull;import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide;import com.google.firebase.auth.FirebaseAuth;import com.google.firebase.auth.FirebaseUser;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.Query;import com.google.firebase.database.ValueEventListener; import java.util.Calendar;import java.util.List;import java.util.Locale; import de.hdodenhof.circleimageview.CircleImageView; public class AdapterChat extends RecyclerView.Adapter<com.example.socialmediaapp.AdapterChat.Myholder> {    private static final int MSG_TYPE_LEFT = 0;    private static final int MSG_TYPR_RIGHT = 1;    Context context;    List<ModelChat> list;    String imageurl;    FirebaseUser firebaseUser;     public AdapterChat(Context context, List<ModelChat> list, String imageurl) {        this.context = context;        this.list = list;        this.imageurl = imageurl;    }     @NonNull    @Override    public Myholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {        if (viewType == MSG_TYPE_LEFT) {            View view = LayoutInflater.from(context).inflate(R.layout.row_chat_left, parent, false);            return new Myholder(view);        } else {            View view = LayoutInflater.from(context).inflate(R.layout.row_chat_right, parent, false);            return new Myholder(view);        }    }     @Override    public void onBindViewHolder(@NonNull Myholder holder, final int position) {        String message = list.get(position).getMessage();        String timeStamp = list.get(position).getTimestamp();        String type = list.get(position).getType();        Calendar calendar = Calendar.getInstance(Locale.ENGLISH);        calendar.setTimeInMillis(Long.parseLong(timeStamp));        String timedate = DateFormat.format("dd/MM/yyyy hh:mm aa", calendar).toString();        holder.message.setText(message);        holder.time.setText(timedate);        try {            Glide.with(context).load(imageurl).into(holder.image);        } catch (Exception e) {         }        if (type.equals("text")) {            holder.message.setVisibility(View.VISIBLE);            holder.mimage.setVisibility(View.GONE);            holder.message.setText(message);        } else {            holder.message.setVisibility(View.GONE);            holder.mimage.setVisibility(View.VISIBLE);            Glide.with(context).load(message).into(holder.mimage);        }         holder.msglayput.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                AlertDialog.Builder builder = new AlertDialog.Builder(context);                builder.setTitle("Delete Message");                builder.setMessage("Are You Sure To Delete This Message");                builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        deleteMsg(position);                    }                });                builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        dialog.dismiss();                    }                });                builder.create().show();            }        });    }     private void deleteMsg(int position) {        final String myuid = FirebaseAuth.getInstance().getCurrentUser().getUid();        String msgtimestmp = list.get(position).getTimestamp();        DatabaseReference dbref = FirebaseDatabase.getInstance().getReference().child("Chats");        Query query = dbref.orderByChild("timestamp").equalTo(msgtimestmp);        query.addListenerForSingleValueEvent(new ValueEventListener() {            @Override            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {                    if (dataSnapshot1.child("sender").getValue().equals(myuid)) {                        // any two of below can be used                        dataSnapshot1.getRef().removeValue();                       /* HashMap<String, Object> hashMap = new HashMap<>();                        hashMap.put("message", "This Message Was Deleted");                        dataSnapshot1.getRef().updateChildren(hashMap);                        Toast.makeText(context,"Message Deleted.....",Toast.LENGTH_LONG).show();*/                    } else {                        Toast.makeText(context, "you can delete only your msg....", Toast.LENGTH_LONG).show();                    }                }            }             @Override            public void onCancelled(@NonNull DatabaseError databaseError) {             }        });    }     @Override    public int getItemCount() {        return list.size();    }     @Override    public int getItemViewType(int position) {        firebaseUser = FirebaseAuth.getInstance().getCurrentUser();        if (list.get(position).getSender().equals(firebaseUser.getUid())) {            return MSG_TYPR_RIGHT;        } else {            return MSG_TYPE_LEFT;        }    }     class Myholder extends RecyclerView.ViewHolder {         CircleImageView image;        ImageView mimage;        TextView message, time, isSee;        LinearLayout msglayput;         public Myholder(@NonNull View itemView) {            super(itemView);            image = itemView.findViewById(R.id.profilec);            message = itemView.findViewById(R.id.msgc);            time = itemView.findViewById(R.id.timetv);            isSee = itemView.findViewById(R.id.isSeen);            msglayput = itemView.findViewById(R.id.msglayout);            mimage = itemView.findViewById(R.id.images);        }    }}
 Step 6: Working with the ChatActivity.java file
We are Reading the user message from “Chats” Node in Firebase. Every time data changes this data will change accordingly 
chatList=new ArrayList<>();
DatabaseReference dbref= FirebaseDatabase.getInstance().getReference().child("Chats");
Loading the Data setting data value using adapter chat 
ModelChat modelChat=dataSnapshot1.getValue(ModelChat.class);
                    if(modelChat.getSender().equals(myuid)&&
                            modelChat.getReceiver().equals(uid)||
                            modelChat.getReceiver().equals(myuid)
                                    && modelChat.getSender().equals(uid)){
                        chatList.add(modelChat);//add the chat in chatlist
                    }
                    adapterChat=new AdapterChat(ChatActivity.this,chatList,image);
                    adapterChat.notifyDataSetChanged();
                    recyclerView.setAdapter(adapterChat);
Sending Messages in Chat Reference node value. Here is how we are saving data in the Firebase Realtime database 
DatabaseReference databaseReference= FirebaseDatabase.getInstance().getReference();
        String timestamp=String.valueOf(System.currentTimeMillis());
        HashMap<String,Object> hashMap=new HashMap<>();
        hashMap.put("sender",myuid);
        hashMap.put("receiver",uid);
        hashMap.put("message",message);
        hashMap.put("timestamp",timestamp);
        hashMap.put("dilihat",false);
        hashMap.put("type","text");
        databaseReference.child("Chats").push().setValue(hashMap);
Below is the code for the ChatActivity.java file. 
Java
package com.example.socialmediaapp; import android.Manifest;import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.ContentValues;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.net.Uri;import android.os.Bundle;import android.provider.MediaStore;import android.text.TextUtils;import android.text.format.DateFormat;import android.view.MenuItem;import android.view.View;import android.widget.EditText;import android.widget.ImageButton;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast; import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import androidx.appcompat.widget.Toolbar;import androidx.core.content.ContextCompat;import androidx.recyclerview.widget.LinearLayoutManager;import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide;import com.google.android.gms.tasks.OnFailureListener;import com.google.android.gms.tasks.OnSuccessListener;import com.google.android.gms.tasks.Task;import com.google.firebase.auth.FirebaseAuth;import com.google.firebase.auth.FirebaseUser;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.Query;import com.google.firebase.database.ValueEventListener;import com.google.firebase.storage.FirebaseStorage;import com.google.firebase.storage.StorageReference;import com.google.firebase.storage.UploadTask; import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.ArrayList;import java.util.Calendar;import java.util.HashMap;import java.util.List;  public class ChatActivity extends AppCompatActivity {    Toolbar toolbar;    RecyclerView recyclerView;    ImageView profile, block;    TextView name, userstatus;    EditText msg;    ImageButton send, attach;    FirebaseAuth firebaseAuth;    String uid, myuid, image;    ValueEventListener valueEventListener;    List<ModelChat> chatList;    AdapterChat adapterChat;     private static final int IMAGEPICK_GALLERY_REQUEST = 300;    private static final int IMAGE_PICKCAMERA_REQUEST = 400;    private static final int CAMERA_REQUEST = 100;    private static final int STORAGE_REQUEST = 200;    String cameraPermission[];    String storagePermission[];    Uri imageuri = null;    FirebaseDatabase firebaseDatabase;    DatabaseReference users;    boolean notify = false;    boolean isBlocked = false;     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_chat);        firebaseAuth = FirebaseAuth.getInstance();                 // initialise the text views and layouts        profile = findViewById(R.id.profiletv);        name = findViewById(R.id.nameptv);        userstatus = findViewById(R.id.onlinetv);        msg = findViewById(R.id.messaget);        send = findViewById(R.id.sendmsg);        attach = findViewById(R.id.attachbtn);        block = findViewById(R.id.block);        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);        linearLayoutManager.setStackFromEnd(true);        recyclerView = findViewById(R.id.chatrecycle);        recyclerView.setHasFixedSize(true);        recyclerView.setLayoutManager(linearLayoutManager);        uid = getIntent().getStringExtra("uid");                 // getting uid of another user using intent        firebaseDatabase = FirebaseDatabase.getInstance();                 // initialising permissions        cameraPermission = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};        storagePermission = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};         checkUserStatus();        users = firebaseDatabase.getReference("Users");        attach.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                showImagePicDialog();            }        });        send.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                notify = true;                String message = msg.getText().toString().trim();                if (TextUtils.isEmpty(message)) {//if empty                    Toast.makeText(ChatActivity.this, "Please Write Something Here", Toast.LENGTH_LONG).show();                } else {                    sendmessage(message);                }                msg.setText("");            }        });                 Query userquery = users.orderByChild("uid").equalTo(uid);        userquery.addValueEventListener(new ValueEventListener() {            @Override            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                // retrieve user data                for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {                    String nameh = "" + dataSnapshot1.child("name").getValue();                    image = "" + dataSnapshot1.child("image").getValue();                    String onlinestatus = "" + dataSnapshot1.child("onlineStatus").getValue();                    String typingto = "" + dataSnapshot1.child("typingTo").getValue();                    if (typingto.equals(myuid)) {// if user is typing to my chat                        userstatus.setText("Typing....");// type status as typing                    } else {                        if (onlinestatus.equals("online")) {                            userstatus.setText(onlinestatus);                        } else {                            Calendar calendar = Calendar.getInstance();                            calendar.setTimeInMillis(Long.parseLong(onlinestatus));                            String timedate = DateFormat.format("dd/MM/yyyy hh:mm aa", calendar).toString();                            userstatus.setText("Last Seen:" + timedate);                        }                    }                    name.setText(nameh);                    try {                        Glide.with(ChatActivity.this).load(image).placeholder(R.drawable.profile_image).into(profile);                    } catch (Exception e) {                     }                }            }             @Override            public void onCancelled(@NonNull DatabaseError databaseError) {             }        });        readMessages();    }      @Override    protected void onPause() {        super.onPause();        String timestamp = String.valueOf(System.currentTimeMillis());        checkOnlineStatus(timestamp);        checkTypingStatus("noOne");    }     @Override    protected void onResume() {        checkOnlineStatus("online");        super.onResume();    }     @Override    public boolean onSupportNavigateUp() {        onBackPressed();        return super.onSupportNavigateUp();    }     private void checkOnlineStatus(String status) {        // check online status        DatabaseReference dbref = FirebaseDatabase.getInstance().getReference("Users").child(myuid);        HashMap<String, Object> hashMap = new HashMap<>();        hashMap.put("onlineStatus", status);        dbref.updateChildren(hashMap);    }     private void checkTypingStatus(String typing) {        DatabaseReference dbref = FirebaseDatabase.getInstance().getReference("Users").child(myuid);        HashMap<String, Object> hashMap = new HashMap<>();        hashMap.put("typingTo", typing);        dbref.updateChildren(hashMap);    }     @Override    protected void onStart() {        checkUserStatus();        checkOnlineStatus("online");        super.onStart();    }     private void readMessages() {        // show message after retrieving data        chatList = new ArrayList<>();        DatabaseReference dbref = FirebaseDatabase.getInstance().getReference().child("Chats");        dbref.addValueEventListener(new ValueEventListener() {            @Override            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                 chatList.clear();                for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {                    ModelChat modelChat = dataSnapshot1.getValue(ModelChat.class);                    if (modelChat.getSender().equals(myuid) &&                            modelChat.getReceiver().equals(uid) ||                            modelChat.getReceiver().equals(myuid)                                    && modelChat.getSender().equals(uid)) {                        chatList.add(modelChat); // add the chat in chatlist                    }                    adapterChat = new AdapterChat(ChatActivity.this, chatList, image);                    adapterChat.notifyDataSetChanged();                    recyclerView.setAdapter(adapterChat);                }            }             @Override            public void onCancelled(@NonNull DatabaseError databaseError) {             }        });    }     private void showImagePicDialog() {        String options[] = {"Camera", "Gallery"};        AlertDialog.Builder builder = new AlertDialog.Builder(ChatActivity.this);        builder.setTitle("Pick Image From");        builder.setItems(options, new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                 if (which == 0) {                    if (!checkCameraPermission()) { // if permission is not given                        requestCameraPermission(); // request for permission                    } else {                        pickFromCamera(); // if already access granted then click                    }                } else if (which == 1) {                    if (!checkStoragePermission()) { // if permission is not given                        requestStoragePermission(); // request for permission                    } else {                        pickFromGallery(); // if already access granted then pick                    }                }            }        });        builder.create().show();    }     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        // request for permission if not given        switch (requestCode) {            case CAMERA_REQUEST: {                if (grantResults.length > 0) {                    boolean camera_accepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;                    boolean writeStorageaccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;                    if (camera_accepted && writeStorageaccepted) {                        pickFromCamera(); // if access granted then click                    } else {                        Toast.makeText(this, "Please Enable Camera and Storage Permissions", Toast.LENGTH_LONG).show();                    }                }            }            break;            case STORAGE_REQUEST: {                if (grantResults.length > 0) {                    boolean writeStorageaccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;                    if (writeStorageaccepted) {                        pickFromGallery(); // if access granted then pick                    } else {                        Toast.makeText(this, "Please Enable Storage Permissions", Toast.LENGTH_LONG).show();                    }                }            }            break;        }    }     @Override    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {        if (resultCode == RESULT_OK) {            if (requestCode == IMAGEPICK_GALLERY_REQUEST) {                imageuri = data.getData(); // get image data to upload                try {                    sendImageMessage(imageuri);                } catch (IOException e) {                    e.printStackTrace();                }            }            if (requestCode == IMAGE_PICKCAMERA_REQUEST) {                try {                    sendImageMessage(imageuri);                } catch (IOException e) {                    e.printStackTrace();                }            }        }        super.onActivityResult(requestCode, resultCode, data);    }     private void sendImageMessage(Uri imageuri) throws IOException {        notify = true;        final ProgressDialog dialog = new ProgressDialog(this);        dialog.setMessage("Sending Image");        dialog.show();                 // If we are sending image as a message        // then we need to find the url of        // image after uploading the        // image in firebase storage        final String timestamp = "" + System.currentTimeMillis();        String filepathandname = "ChatImages/" + "post" + timestamp; // filename        Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageuri);        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();        bitmap.compress(Bitmap.CompressFormat.PNG, 100, arrayOutputStream); // compressing the image using bitmap        final byte[] data = arrayOutputStream.toByteArray();        StorageReference ref = FirebaseStorage.getInstance().getReference().child(filepathandname);        ref.putBytes(data).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {            @Override            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {                dialog.dismiss();                Task<Uri> uriTask = taskSnapshot.getStorage().getDownloadUrl();                while (!uriTask.isSuccessful()) ;                String downloadUri = uriTask.getResult().toString(); // getting url if task is successful                 if (uriTask.isSuccessful()) {                    DatabaseReference re = FirebaseDatabase.getInstance().getReference();                    HashMap<String, Object> hashMap = new HashMap<>();                    hashMap.put("sender", myuid);                    hashMap.put("receiver", uid);                    hashMap.put("message", downloadUri);                    hashMap.put("timestamp", timestamp);                    hashMap.put("dilihat", false);                    hashMap.put("type", "images");                    re.child("Chats").push().setValue(hashMap); // push in firebase using unique id                    final DatabaseReference ref1 = FirebaseDatabase.getInstance().getReference("ChatList").child(uid).child(myuid);                    ref1.addValueEventListener(new ValueEventListener() {                        @Override                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                            if (!dataSnapshot.exists()) {                                ref1.child("id").setValue(myuid);                            }                        }                         @Override                        public void onCancelled(@NonNull DatabaseError databaseError) {                         }                    });                    final DatabaseReference ref2 = FirebaseDatabase.getInstance().getReference("ChatList").child(myuid).child(uid);                    ref2.addValueEventListener(new ValueEventListener() {                        @Override                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                            if (!dataSnapshot.exists()) {                                ref2.child("id").setValue(uid);                            }                        }                         @Override                        public void onCancelled(@NonNull DatabaseError databaseError) {                         }                    });                }            }        }).addOnFailureListener(new OnFailureListener() {            @Override            public void onFailure(@NonNull Exception e) {             }        });    }     private Boolean checkCameraPermission() {        boolean result = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == (PackageManager.PERMISSION_GRANTED);        boolean result1 = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED);        return result && result1;    }     private void requestCameraPermission() {        requestPermissions(cameraPermission, CAMERA_REQUEST);    }     private void pickFromCamera() {        ContentValues contentValues = new ContentValues();        contentValues.put(MediaStore.Images.Media.TITLE, "Temp_pic");        contentValues.put(MediaStore.Images.Media.DESCRIPTION, "Temp Description");        imageuri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);        Intent camerIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);        camerIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri);        startActivityForResult(camerIntent, IMAGE_PICKCAMERA_REQUEST);    }     private void pickFromGallery() {        Intent galleryIntent = new Intent(Intent.ACTION_PICK);        galleryIntent.setType("image/*");        startActivityForResult(galleryIntent, IMAGEPICK_GALLERY_REQUEST);    }     private Boolean checkStoragePermission() {        boolean result = ContextCompat.checkSelfPermission(ChatActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED);        return result;    }     private void requestStoragePermission() {        requestPermissions(storagePermission, STORAGE_REQUEST);    }     private void sendmessage(final String message) {        // creating a reference to store data in firebase        // We will be storing data using current time in "Chatlist"        // and we are pushing data using unique id in "Chats"        DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();        String timestamp = String.valueOf(System.currentTimeMillis());        HashMap<String, Object> hashMap = new HashMap<>();        hashMap.put("sender", myuid);        hashMap.put("receiver", uid);        hashMap.put("message", message);        hashMap.put("timestamp", timestamp);        hashMap.put("dilihat", false);        hashMap.put("type", "text");        databaseReference.child("Chats").push().setValue(hashMap);        final DatabaseReference ref1 = FirebaseDatabase.getInstance().getReference("ChatList").child(uid).child(myuid);        ref1.addValueEventListener(new ValueEventListener() {            @Override            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                if (!dataSnapshot.exists()) {                    ref1.child("id").setValue(myuid);                }            }             @Override            public void onCancelled(@NonNull DatabaseError databaseError) {             }        });        final DatabaseReference ref2 = FirebaseDatabase.getInstance().getReference("ChatList").child(myuid).child(uid);        ref2.addValueEventListener(new ValueEventListener() {            @Override            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                 if (!dataSnapshot.exists()) {                    ref2.child("id").setValue(uid);                }            }             @Override            public void onCancelled(@NonNull DatabaseError databaseError) {             }        });    }     @Override    public boolean onOptionsItemSelected(@NonNull MenuItem item) {        if (item.getItemId() == R.id.logout) {            firebaseAuth.signOut();            checkUserStatus();        }        return super.onOptionsItemSelected(item);    }     private void checkUserStatus() {        FirebaseUser user = firebaseAuth.getCurrentUser();        if (user != null) {            myuid = user.getUid();        }     }}
 Output: 
Step 1: Working with the ModelChatlist.xml file
Getting the id of users to whom we have sent messages. 
Java
package com.example.socialmediaapp; class ModelChatList {     public String getId() {        return id;    }     public void setId(String id) {        this.id = id;    }     public ModelChatList() {    }     public ModelChatList(String id) {        this.id = id;    }     String id;}
 Step 2: Working with the AdapterChatList.java file
Showing the users and the last message sent in the chat. 
Java
package com.example.socialmediaapp; import android.content.Context;import android.content.Intent;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView; import androidx.annotation.NonNull;import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide;import com.google.firebase.auth.FirebaseAuth; import java.util.HashMap;import java.util.List; public class AdapterChatList extends RecyclerView.Adapter<AdapterChatList.Myholder> {     Context context;    FirebaseAuth firebaseAuth;    String uid;     public AdapterChatList(Context context, List<ModelUsers> users) {        this.context = context;        this.usersList = users;        lastMessageMap = new HashMap<>();        firebaseAuth = FirebaseAuth.getInstance();        uid = firebaseAuth.getUid();    }     List<ModelUsers> usersList;    private HashMap<String, String> lastMessageMap;     @NonNull    @Override    public Myholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {        View view = LayoutInflater.from(context).inflate(R.layout.row_chatlist, parent, false);        return new Myholder(view);    }     @Override    public void onBindViewHolder(@NonNull Myholder holder, final int position) {         final String hisuid = usersList.get(position).getUid();        String userimage = usersList.get(position).getImage();        String username = usersList.get(position).getName();        String lastmess = lastMessageMap.get(hisuid);        holder.name.setText(username);        holder.block.setImageResource(R.drawable.ic_unblock);                // if no last message then Hide the layout        if (lastmess == null || lastmess.equals("default")) {            holder.lastmessage.setVisibility(View.GONE);        } else {            holder.lastmessage.setVisibility(View.VISIBLE);            holder.lastmessage.setText(lastmess);        }        try {            // loading profile pic of user            Glide.with(context).load(userimage).into(holder.profile);        } catch (Exception e) {         }                 // redirecting to chat activity on item click        holder.itemView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(context, ChatActivity.class);                                // putting uid of user in extras                intent.putExtra("uid", hisuid);                context.startActivity(intent);            }        });     }     // setting last message sent by users.    public void setlastMessageMap(String userId, String lastmessage) {        lastMessageMap.put(userId, lastmessage);    }     @Override    public int getItemCount() {        return usersList.size();    }     class Myholder extends RecyclerView.ViewHolder {        ImageView profile, status, block, seen;        TextView name, lastmessage;         public Myholder(@NonNull View itemView) {            super(itemView);            profile = itemView.findViewById(R.id.profileimage);            status = itemView.findViewById(R.id.onlinestatus);            name = itemView.findViewById(R.id.nameonline);            lastmessage = itemView.findViewById(R.id.lastmessge);            block = itemView.findViewById(R.id.blocking);            seen = itemView.findViewById(R.id.seen);        }    }}
 Step 3: Working with the fragment_chatlist.xml file
Showing all the users using the recycler view. 
XML
<?xml version="1.0" encoding="utf-8"?><FrameLayout    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=".ChatListFragment">     <androidx.recyclerview.widget.RecyclerView        android:id="@+id/chatlistrecycle"        android:layout_width="match_parent"        android:layout_height="match_parent"        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"        tools:listitem="@layout/row_chatlist" /> </FrameLayout>
 Step 4: Working with the ChatlistFragment.java file
Here we are showing all the users to whom we have sent messages. This is how we will get the last message of the current user. If the message type is images then simply set the last message as “Sent a photo”. 
if(chat.getReceiver().equals(firebaseUser.getUid())&&
                            chat.getSender().equals(uid)||
                            chat.getReceiver().equals(uid)&&
                                    chat.getSender().equals(firebaseUser.getUid())){
                        if(chat.getType().equals("images")){
                            lastmess="Sent a Photo";
                        }
                        else {
                            lastmess = chat.getMessage();
                        }
                    }
Below is the code for the ChatlistFragment.java file. 
Java
package com.example.socialmediaapp; import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup; import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.fragment.app.Fragment;import androidx.recyclerview.widget.RecyclerView; import com.google.firebase.auth.FirebaseAuth;import com.google.firebase.auth.FirebaseUser;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.ArrayList;import java.util.List; /** * A simple {@link Fragment} subclass. */public class ChatListFragment extends Fragment {     FirebaseAuth firebaseAuth;    RecyclerView recyclerView;    List<ModelChatList> chatListList;    List<ModelUsers> usersList;    DatabaseReference reference;    FirebaseUser firebaseUser;    AdapterChatList adapterChatList;    List<ModelChat> chatList;     public ChatListFragment() {        // Required empty public constructor    }      @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {                 // Inflate the layout for this fragment        View view = inflater.inflate(R.layout.fragment_chat_list, container, false);        firebaseAuth = FirebaseAuth.getInstance();                 // getting current user        firebaseUser = FirebaseAuth.getInstance().getCurrentUser();        recyclerView = view.findViewById(R.id.chatlistrecycle);        chatListList = new ArrayList<>();        chatList = new ArrayList<>();        reference = FirebaseDatabase.getInstance().getReference("ChatList").child(firebaseUser.getUid());        reference.addValueEventListener(new ValueEventListener() {            @Override            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                chatListList.clear();                for (DataSnapshot ds : dataSnapshot.getChildren()) {                    ModelChatList modelChatList = ds.getValue(ModelChatList.class);                    if (!modelChatList.getId().equals(firebaseUser.getUid())) {                        chatListList.add(modelChatList);                    }                 }                loadChats();            }             @Override            public void onCancelled(@NonNull DatabaseError databaseError) {             }        });        return view;     }     // loading the user chat layout using chat node    private void loadChats() {        usersList = new ArrayList<>();        reference = FirebaseDatabase.getInstance().getReference("Users");        reference.addValueEventListener(new ValueEventListener() {            @Override            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                usersList.clear();                for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {                    ModelUsers user = dataSnapshot1.getValue(ModelUsers.class);                    for (ModelChatList chatList : chatListList) {                        if (user.getUid() != null && user.getUid().equals(chatList.getId())) {                            usersList.add(user);                            break;                        }                    }                    adapterChatList = new AdapterChatList(getActivity(), usersList);                    recyclerView.setAdapter(adapterChatList);                                         // getting last message of the user                    for (int i = 0; i < usersList.size(); i++) {                        lastMessage(usersList.get(i).getUid());                    }                }            }             @Override            public void onCancelled(@NonNull DatabaseError databaseError) {             }        });    }     private void lastMessage(final String uid) {        DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Chats");        ref.addValueEventListener(new ValueEventListener() {            @Override            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {                String lastmess = "default";                for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {                    ModelChat chat = dataSnapshot1.getValue(ModelChat.class);                    if (chat == null) {                        continue;                    }                    String sender = chat.getSender();                    String receiver = chat.getReceiver();                    if (sender == null || receiver == null) {                        continue;                    }                    // checking for the type of message if                    // message type is image then set                    // last message as sent a photo                    if (chat.getReceiver().equals(firebaseUser.getUid()) &&                            chat.getSender().equals(uid) ||                            chat.getReceiver().equals(uid) &&                                    chat.getSender().equals(firebaseUser.getUid())) {                        if (chat.getType().equals("images")) {                            lastmess = "Sent a Photo";                        } else {                            lastmess = chat.getMessage();                        }                    }                }                adapterChatList.setlastMessageMap(uid, lastmess);                adapterChatList.notifyDataSetChanged();            }             @Override            public void onCancelled(@NonNull DatabaseError databaseError) {             }        });    }     @Override    public void onCreate(@Nullable Bundle savedInstanceState) {        setHasOptionsMenu(true);        super.onCreate(savedInstanceState);    } }
 Output: 
For all the drawable file used in this article please refer to this link: https://drive.google.com/drive/folders/1M_knOH_ugCuwSP5nkYzeD4dRp-Honzbe?usp=sharing
Below is the file structure after performing these operations:
 
surinderdawra388
rkbhola5
Firebase
Android
Java
Java
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.