Open In App

How to Implement Chat Functionality in Social Media Android App?

Last Updated : 09 May, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

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 By Step Implementation

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 version="1.0" encoding="utf-8"?>
<LinearLayout
    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




<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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: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
    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: 

Showing All Chat in ChatList Fragment

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: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:

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads