How to Implement Chat Functionality in Social Media Android App?

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:

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

< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" 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" /> 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" /> 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" /> 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" /> 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" />

XML

< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" 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" /> 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" /> 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" /> 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" /> android:id = "@+id/isSeen" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:gravity = "end" android:text = "Delivered" android:textAlignment = "textEnd" />

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

< RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android" 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" > 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" /> android:id = "@+id/onlinetv" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:text = "Online" android:textColor = "@color/colorWhite" android:textStyle = "bold" /> 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" /> < 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" /> 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" />

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

< androidx.cardview.widget.CardView xmlns:android = "http://schemas.android.com/apk/res/android" 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" /> 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" /> 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" /> 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" /> 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" />

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 private static final int MSG_TYPE_LEFT = 0 ; private static final int MSG_TYPR_RIGHT = 1 ; Context context; String imageurl; FirebaseUser firebaseUser; public AdapterChat(Context context, List list, String imageurl) this .context = context; this .list = list; this .imageurl = imageurl; 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); View view = LayoutInflater.from(context).inflate(R.layout.row_chat_right, parent, false ); return new Myholder(view); 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); 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); holder.message.setVisibility(View.GONE); holder.mimage.setVisibility(View.VISIBLE); Glide.with(context).load(message).into(holder.mimage); holder.msglayput.setOnClickListener( new View.OnClickListener() < 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() < public void onClick(DialogInterface dialog, int which) < deleteMsg(position); builder.setNegativeButton( "Cancel" , new DialogInterface.OnClickListener() < 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() < 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 hashMap = new HashMap<>(); hashMap.put("message", "This Message Was Deleted"); dataSnapshot1.getRef().updateChildren(hashMap); Toast.makeText(context,"Message Deleted. ",Toast.LENGTH_LONG).show(); Toast.makeText(context, "you can delete only your msg. " , Toast.LENGTH_LONG).show(); public void onCancelled( @NonNull DatabaseError databaseError) < public int getItemCount() < return list.size(); public int getItemViewType( int position) < firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); if (list.get(position).getSender().equals(firebaseUser.getUid())) < return MSG_TYPR_RIGHT; 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 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.