How do I align ListView items based on a condition? - android

I am creating a chat program with Android Studio, and I am having trouble figuring out a way to show a list of messages that are left aligned for incoming messages and right aligned for outgoing messages. Right now, they are all left aligned.
What is the simplest way to left and right align text based on if the user id is the same as the current logged in user id? Below is what it looks like right now.
Current List View Sample

Assuming you are using Firebase for this app and getting the currently logged-in user details, you can make some changes to the Adapter class (MessageAdapter in this example).
Credits to numerous youtube videos and online resources that I used to do this in my app
Create chat_item_right.xml and chat_item_left.xml for 2 different users
Make some changes in the MessageAdapter class
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MyViewHolder> {
public static final int MSG_TYPE_LEFT = 0;
public static final int MSG_TYPE_RIGHT = 1;
private Context mContext;
private List<Chat> mChat;
private String imageurl;
private FirebaseUser firebaseUser;
public MessageAdapter(Context mContext, List<Chat> mChat, String imageurl) {
this.mContext = mContext;
this.mChat = mChat;
this.imageurl = imageurl;
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// Get the view type and create the right view
View view;
if (viewType == MSG_TYPE_RIGHT) {
view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_right, parent, false);
}
else {
view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_left, parent, false);
}
return new MyViewHolder(view);
}
// Method to get each chat message and show it
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
Chat chat = mChat.get(position);
if (imageurl.equals("default")) {
holder.profile_image.setImageResource(R.mipmap.ic_launcher);
}
else {
Glide.with(mContext).load(imageurl).into(holder.profile_image);
}
if (chat.getType().equals("text")) {
holder.show_message.setText(chat.getMessage());
}
else if (chat.getType().equals("image")) {
// Depends on your code here
Glide.with(mContext).load(chat.getMessage()).into(holder.image_message);
}
}
#Override
public int getItemCount() {
return mChat.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView show_message, txt_seen;
private ImageView profile_image, image_message;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
show_message = itemView.findViewById(R.id.show_message);
profile_image = itemView.findViewById(R.id.profile_image);
txt_seen = itemView.findViewById(R.id.txt_seen);
image_message = itemView.findViewById(R.id.image_message);
}
}
#Override
public int getItemViewType(int position) {
// If i'm the sender show message on right else show it on left
if (mChat.get(position).getSender().equals(firebaseUser.getUid())) {
return MSG_TYPE_RIGHT;
}
else {
return MSG_TYPE_LEFT;
}
}
}
Call this in your MessageActivity or Fragment class
private MessageAdapter messageAdapter;
private List<Chat> mChat;
private DatabaseReference reference;
private FirebaseUser firebaseUser;
private String userid;
. // All your relevant code here
.
.
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
// You should have stored the current user the moment you have logged in
// in SharedPrefs perhaps (or DataStore or etc) so that we can compare later
// during set view_item to left or right
// For e.g sending the userID as bundle from Login Page to MessageActivity
// intent = new Intent(this, MessageActivity.class);
// bundle.putString("userid", user);
userid = intent.getStringExtra("userid");
private void readMessages(final String myId, final String userid, final String imageurl) {
mChat = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("Chats");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mChat.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Chat chat = snapshot.getValue(Chat.class);
// Add to chat list only messages between you and the sender
assert chat != null;
// The below code depends on your Chat object class
// So please modify accordingly
if (chat.getReceiver() != null && chat.getSender() != null) {
if (chat.getReceiver().equals(myId) && chat.getSender().equals(userid) ||
chat.getReceiver().equals(userid) && chat.getSender().equals(myId)) {
mChat.add(chat);
}
}
}
// Create a new adapter and set it to our view
messageAdapter = new MessageAdapter(MessageActivity.this, mChat, imageurl);
recyclerView.setAdapter(messageAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
// Call the function
readMessages(firebaseUser.getUid(), userid, user.getImageURL());

Related

FirebaseRecyclerAdapter model returning null values

I'm trying to make a comment system for posts on my social media app. In my database each post has a section inside of "comments" table, like so:
"hypno--######" is the title of the social media post. It Contains the comment, user id of the user who posted the comment, and a unixtimestamp when the comment was posted. Each comment is titled after the time it was posted.
This is the Comment class
public class comment {
public String uID;
public String comment_t;
public long unixTimestamp;
public comment() {
// Default constructor required for calls to DataSnapshot.getValue(User.class)
}
public comment(String uID, String comment_t, long unixTimestamp) {
this.uID = uID;
this.comment_t = comment_t;
this.unixTimestamp = unixTimestamp;
}
public String getuID() {
return uID;
}
public void setuID(String uID) {
this.uID = uID;
}
public String getComment() {return comment_t;}
public void setComment() {this.comment_t = comment_t; }
public long getUnixTimestamp() {
return unixTimestamp;
}
}
This is the Comment Adapter:
Public class Adapter_Comment extends FirebaseRecyclerAdapter<comment, Adapter_Comment.ViewHolder_com> {
private DatabaseReference mDatabase;
private static final String TAG = "RecyclerViewAdapter";
private Context mContext;
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
private static AppCompatActivity unwrap(Context context) {
while (!(context instanceof Activity) && context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
return (AppCompatActivity) context;
}
public Adapter_Comment(#NonNull FirebaseRecyclerOptions<comment> options) {
super(options);
//this.mContext = mContext;
}
#NonNull
#Override
public ViewHolder_com onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_comment, parent, false);
mDatabase = FirebaseDatabase.getInstance().getReference();
return new ViewHolder_com(view);
}
#Override
protected void onBindViewHolder(#NonNull ViewHolder_com holder, int position, #NonNull comment model) {
mDatabase = FirebaseDatabase.getInstance().getReference();
long dv = model.getUnixTimestamp()*-1000;
Date df = new java.util.Date(dv);
String vv = new SimpleDateFormat("MM dd, yyyy hh:mma", Locale.ENGLISH).format(df);
holder.time.setText(vv);
String com = model.getComment();
holder.comment_text.setText(com);
mDatabase.child("users").child(model.getuID()).child("profileUrl").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists())
{
final String picUrl = snapshot.getValue(String.class);
Glide.with(holder.postPfp.getContext()).load(picUrl).into(holder.postPfp);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) { }
});
holder.postPfp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//AppCompatActivity activity = (AppCompatActivity) v.getContext();
AppCompatActivity activity = unwrap(v.getContext());
Fragment OtherProfileFragment = new OtherProfileFragment();
Bundle bundle = new Bundle();
bundle.putString("key", model.getuID());
OtherProfileFragment.setArguments(bundle);
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, OtherProfileFragment).addToBackStack(null).commit();
}
});
}
public class ViewHolder_com extends RecyclerView.ViewHolder {
TextView comment_text;
CircleImageView postPfp;
TextView time;
RelativeLayout comment_layout;
public ViewHolder_com(#NonNull View itemView) {
super(itemView);
postPfp = itemView.findViewById(R.id.iv_comment_icon);
comment_text = itemView.findViewById(R.id.tv_comment_text);
time = itemView.findViewById(R.id.tv_comment_time);
comment_layout = itemView.findViewById(R.id.comment_layout);
}
}
}
This is Comment Fragment:
public class CommentFragment extends Fragment {
private DatabaseReference mDatabase;
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
View view;
String value;
RecyclerView recyclerView;
Query query;
TextView comment_text;
long unixTime = System.currentTimeMillis() / 1000L;
public long globalUnix;
Button comment_post;
String comment_string;
Adapter_Comment adapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_comment, container, false);
value = getArguments().getString("key");
mDatabase = FirebaseDatabase.getInstance().getReference();
recyclerView = view.findViewById(R.id.recyclerv_comment);
comment_text = view.findViewById(R.id.tv_comment_type);
comment_post = view.findViewById(R.id.btn_comment_post);
globalUnix = (unixTime * -1);
comment_post.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(comment_text.getText().toString() == NULL){
Toast.makeText(getActivity(), "No Comment Typed", Toast.LENGTH_LONG).show();
}
else{
comment com = new comment();
com.uID = user.getUid();
com.comment_t = comment_text.getText().toString();
com.unixTimestamp = globalUnix;
mDatabase.child("comments").child(value).child(globalUnix + "").setValue(com);
}
}
});
initRecyclerView();
return view;
}
private void initRecyclerView(){
//Log.d(TAG, "initRecyclerView: init recyclerView");
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
query = FirebaseDatabase.getInstance().getReference().child("comments").orderByValue();
FirebaseRecyclerOptions<comment> options = new FirebaseRecyclerOptions.Builder<comment>().setQuery(query, comment.class).build();
adapter = new Adapter_Comment(options);
recyclerView.setAdapter(adapter);
adapter.startListening();
adapter.notifyDataSetChanged();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Inside of the adapter I'm using the comment model, to get the uID, comment and timestamp to fill the holder, however when i set these values im getting null values. Is there something im missing when trying to connect the adapter/firebase and model/holder?
long dv = model.getUnixTimestamp()*-1000;
Date df = new java.util.Date(dv);
String vv = new SimpleDateFormat("MM dd, yyyy hh:mma", Locale.ENGLISH).format(df);
holder.time.setText(vv);
String com = model.getComment();
holder.comment_text.setText(com);
mDatabase.child("users").child(model.getuID()).child("profileUrl").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists())
{
final String picUrl = snapshot.getValue(String.class);
Glide.with(holder.postPfp.getContext()).load(picUrl).into(holder.postPfp);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) { }
});
There's really too much going on in here, but...
As far as I can see you're creating a FirebaseUI adapter on FirebaseDatabase.getInstance().getReference().child("comments"). FirebaseUI adapters show the direct child nodes of the node you pass in, so in your case it'll create one view for the hypno---...196 node. You're trying to read a Comment object from there, but don't exist until one level lower in your JSON.
So you can:
Either show the comments for one post, by basing the adapter off of that. So: FirebaseDatabase.getInstance().getReference().child("comments").child("hypno---...196") (which the real key in there).
Or you can show one piece of information about each post, for example its key.
If you want to show a flat list of comments for all posts through the FirebaseUI adapter, you'll have to store a flat list of comments across all posts in your database too.

New user is part of a group it was never added to

I'm currently working on an app in which users can create groups and add members to groups. Today I created a new user to test the app. When I logged in this new user I checked to see if it was a part of any groups, which I didn't expect it to be seeing as it was new. And it wasn't. But then when I logged in my usual user and clicked groups I saw the name of the test user. Why does it appear that this user is a part of a group it was never added to?
It should be noted that when looking through my firebase this test user doesn't appear to have been invited either. I'm using firestore recycler adapter to fetch data in a recyclerView.
Below is the code for my adapter responsible for adding members to a specific group.
FirestoreMemberAdapter.java:
public class FirestoreMemberAdapter extends FirestoreRecyclerAdapter<MemberModel, FirestoreMemberAdapter.MemberViewHolder> {
private static final String TAG = FirestoreMemberAdapter.class.getSimpleName();
private Context context;
private String projectId;
private String projectName;
public FirestoreMemberAdapter(#NonNull FirestoreRecyclerOptions<MemberModel> options, Context context, String projectId, String projectName) {
super(options);
this.context = context;
this.projectName = projectName;
this.projectId = projectId;
}
#Override
protected void onBindViewHolder(#NonNull MemberViewHolder holder, int position, #NonNull final MemberModel model) {
holder.mTextView.setText(model.getName());
if (model.getProfile_image() == null) {
Picasso.get().load(R.drawable.profile_image).into(holder.mImageview);
} else {
Picasso.get().load(model.getProfile_image()).into(holder.mImageview);
}
holder.mLinearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "onClick: Clicked on FirestoreMemberAdapter ");
Intent intent = new Intent(context, ProfileMemberPage.class);
intent.putExtra(StringCreator.PROJECT_TITLE, projectName);
intent.putExtra(StringCreator.PROJECT_ID, projectId);
intent.putExtra(StringCreator.NAME, model.getName());
intent.putExtra(StringCreator.EMAIL, model.getEmail());
intent.putExtra(StringCreator.USER_ID, model.getUser_id());
intent.putExtra(StringCreator.USER_INFORMATION, model.getUser_information());
context.startActivity(intent);
}
});
}
#NonNull
#Override
public MemberViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_projectmembers, parent, false);
return new MemberViewHolder(view);
}
public class MemberViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mLinearLayout;
private TextView mTextView;
private ImageView mImageview;
public MemberViewHolder(#NonNull View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.memberTitle);
mLinearLayout = itemView.findViewById(R.id.layout_members);
mImageview = itemView.findViewById(R.id.memberImage);
}
}
}
Here is the activity in wihch the adapter is used.
projectClicked.java:
//widgets
private RecyclerView recyclerViewMembers;
private TextView projectName;
private Button cameraBtn;
private FloatingActionButton addUserBtn;
//Firebase
private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
private Query query;
private FirestoreRecyclerOptions<MemberModel> options;
private FirestoreMemberAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_project_clicked);
projectName = findViewById(R.id.projectName);
addUserBtn = findViewById(R.id.addUserBtn);
cameraBtn = findViewById(R.id.cameraBtn);
initRecyclerView();
addUserBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent newIntent = new Intent(projectClicked.this, UserToProject.class);
Bundle projectBundle = getIntent().getExtras();
if (projectBundle != null) {
newIntent.putExtras(projectBundle);
}
startActivity(newIntent);
}
});
}
private void initRecyclerView() {
Log.d(TAG, "InitRecyclerView: init recyclerview");
if (getIntent().hasExtra(StringCreator.PROJECT_TITLE) && getIntent().hasExtra(StringCreator.PROJECT_ID)) {
final String pName = getIntent().getStringExtra(StringCreator.PROJECT_TITLE);
final String pID = getIntent().getStringExtra(StringCreator.PROJECT_ID);
projectName.setText(pName);
recyclerViewMembers = findViewById(R.id.recyclerView_members);
query = firebaseFirestore.collection("users");
options = new FirestoreRecyclerOptions.Builder<MemberModel>().setQuery(query, MemberModel.class).build();
adapter = new FirestoreMemberAdapter(options, projectClicked.this, pID, pName);
recyclerViewMembers.setHasFixedSize(true);
recyclerViewMembers.setAdapter(adapter);
recyclerViewMembers.setLayoutManager(new LinearLayoutManager(projectClicked.this));
}
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
Hope this makes sense, please reach out if it doesn't. Thank you in advance.
As #McSlinPlay mentioned, the reason could be pointed out to your code in projectClicked.java where you created your query and all the users (including the test user) are part of this collection:
query = firebaseFirestore.collection("users");

How do i arrange data in Recyclerview order by date from Firebase

I am trying to built a messaging app and it works fine but i want to do some modification instead of seeing users with respect to there name i want to see users with respect to last message . Currently when i receive a new message it doesn't come up in list instead it stays in recyclerview at same position what i want is to see the user on top to whom i sent or received the latest message. I do have have timestamp with each message which is sent by user
Messages Structure
RecyclerAdapter
public class ChatsFragmentAdapter extends RecyclerView.Adapter<ChatsFragmentAdapter.ViewHolder2> {
private Context mContext;
private List<User> mUsers;
String theLastMessage;
String TAG = "AdTag";
public ChatsFragmentAdapter(Context mContext, List<User> mUsers) {
this.mContext = mContext;
this.mUsers = mUsers;
}
#NonNull
#Override
public ChatsFragmentAdapter.ViewHolder2 onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(mContext).inflate(R.layout.user_item,parent,false);
return new ChatsFragmentAdapter.ViewHolder2(view);
}
#Override
public void onBindViewHolder(#NonNull ChatsFragmentAdapter.ViewHolder2 holder, int position) {
final User user=mUsers.get(position);
lastMessage(user.getId(), holder.last_msg);
}
#Override
public int getItemCount() {
return mUsers.size();
}
public class ViewHolder2 extends RecyclerView.ViewHolder{
public TextView username;
public ImageView profile_image;
private ImageView img_on;
private ImageView img_off;
private TextView last_msg;
public ViewHolder2(#NonNull View itemView) {
super(itemView);
username=itemView.findViewById(R.id.username);
profile_image=itemView.findViewById(R.id.profile_image);
img_on = itemView.findViewById(R.id.img_on);
img_off = itemView.findViewById(R.id.img_off);
last_msg=itemView.findViewById(R.id.last_msg);
}
}
private void lastMessage(final String userid, final TextView last_msg) {
theLastMessage = "default";
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
String fuserkey;
fuserkey = FirebaseAuth.getInstance().getCurrentUser().getUid();
int i = (fuserkey).compareTo(userid);
if (+i >= 1) {
ChatKey = userid + fuserkey;
} else if (+i < 1) {
ChatKey = fuserkey + userid;
} else if (+i == 0) {
ChatKey = "";
}
if (ChatKey !=null) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Chats").child(ChatKey);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Chat chat = snapshot.getValue(Chat.class);
if (firebaseUser != null && chat != null) {
if (chat.getReceiver().equals(firebaseUser.getUid()) && chat.getSender().equals(userid) ||
chat.getReceiver().equals(userid) && chat.getSender().equals(firebaseUser.getUid())) {
theLastMessage = chat.getMessage();
if (!chat.isIsseen()) {
last_msg.setTypeface(Typeface.DEFAULT_BOLD);
}
}
}
}
switch (theLastMessage) {
case "default":
last_msg.setText("No Message");
break;
default:
last_msg.setText(theLastMessage);
break;
}
theLastMessage = "default";
Log.d(TAG, "Last Message : " + theLastMessage);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
}
According to the Firebase documentation, you will have to sort it when you get the instance reference.
Currently, you have this:
FirebaseDatabase.getInstance().getReference("Chats").child(ChatKey);
You need to change to something like this:
FirebaseDatabase.getInstance().getReference("Chats").child(ChatKey).orderByKey("timestamp");
But I think that in order to use it you will have to change your structure or add keys.
Here is the explanation of how sorting methods works.

Accessing a child within a child firebase

This is not a duplicate.
I am trying to access a child within a child in firebase and then putting that child into a recycler adapter. It won't show in the recycler adapter. There is a similar question on here to this but when implementing it, it still doesn't work.
Currently using an adapter, a messages object and a fragment.
Fragment Activity
private ArrayList<Messages> results = new ArrayList<>();
private void listenForChat() {
final DatabaseReference userDb = FirebaseDatabase.getInstance().getReference().child("users").child(currentUid)
.child("receivedMessages");
messageUrlDb = userDb.child("messageUrl");
messageUrlDb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String message = "";
if (dataSnapshot.child("messageUrl").getValue() != null)
message = dataSnapshot.child("messageUrl").getValue().toString();
Messages obj = new Messages(message, name, image);
if (!results.contains(obj)) {
results.add(obj);
messagesList.setAdapter(mAdapter);
mAdapter.notifyDataSetChanged();
initializeDisplay();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { }
});
}
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ChatViewHolders> {
private List<Messages> mMessageList;
private List<UserObject> usersList;
private Context context;
private DisplayTextFragment displayTextFragment;
private String message;
public ChatAdapter(List<Messages> mMessageList, Context context) {
this.mMessageList = mMessageList;
this.context = context;
}
#Override
public ChatViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_layout, null);
ChatViewHolders rcv = new ChatViewHolders(v);
return rcv;
}
#Override
public void onBindViewHolder(final ChatViewHolders holder, int position) {
holder.messageText.setText(mMessageList.get(position).getMessage());
}
#Override
public int getItemCount() {
return mMessageList.size();
}
public class ChatViewHolders extends RecyclerView.ViewHolder {
public TextView messageText, timeSent, mName;
ImageView mProfile;
LinearLayout mLayout;
public ChatViewHolders(View view) {
super(view);
messageText = (TextView) view.findViewById(R.id.message_text);
mLayout = itemView.findViewById(R.id.layout);
}
}
}
I am trying access (messageUrl) users -> receivedMessages -> messageUrl. However as there is a key they I assume it doesn't as far as messagesUrl. For the recycler adapter it needs take in messagesUrl as a string and update accordingly but I just can't do it.
If any more code is needed I can post. Thank you.
This is how you're attaching your ValueEventListener:
final DatabaseReference userDb = FirebaseDatabase.getInstance().getReference().child("users").child(currentUid)
.child("receivedMessages");
messageUrlDb = userDb.child("messageUrl");
messageUrlDb.addValueEventListener(new ValueEventListener() {
If we take the path from this code, you're attaching the listener to /users/$uid/receivedMessages/messageUrl. This path doesn't exist in the data you showed, so your onDataChanged will get called with an empty snapshot.
If you want to read all messages for the user, you should attach your listener to /users/$uid/receivedMessages and parse the snapshot inside onDataChanged:
final DatabaseReference userDb = FirebaseDatabase.getInstance().getReference().child("users").child(currentUid)
.child("receivedMessages");
userDb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userMessages: dataSnapshot.getChildren()) {
for (DataSnapshot messageSnapshot: userMessages.getChildren()) {
System.out.println(messageSnapshot.getKey()+": "+messageSnapshot.getChild("messageUrl").getValue(String.class));
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
This loops over the two level of child nodes you have under the user's receivedMessages node.

I want to get the list of ids of users I select in recyclerview in order to add them to group chat

I am creating a chat app similar to that of whatsapp and in the part where user creates a group, i want to add all users i select from the list, in other words, and return their ids so they can stored together in firebase in order that messages sent in that particular group will reach every user in the group. But am lost on how to go about that. Below is the code in my recyclerView:
public class RecyclerViewAdapterAddUsers extends RecyclerView.Adapter<RecyclerViewAdapterAddUsers.ViewHolder> {
Admin admin;
// variable to store admin uid from sharePreference
//String admin_uid;
private Context mCtx;
private List<Users> mUsers;
private boolean isChat;
// string variable to contain lastMessage from user
private String theLastMessage;
public RecyclerViewAdapterAddUsers(Context mCtx, List<Users> mUsers, boolean isChat){
this.mCtx = mCtx;
this.mUsers = mUsers;
this.isChat = isChat;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_add_users,parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
// gets the positions of the all users
final Users users = mUsers.get(position);
// sets username to the text of the textView
holder.username.setText(users.getUsername());
if(users.getImageUrl() == null){
// loads the default placeholder into ImageView if ImageUrl is null
holder.profile_pic.setImageResource(R.drawable.ic_person_unknown);
}
else{
// loads users image into the ImageView
Glide.with(mCtx).load(users.getImageUrl()).into(holder.profile_pic);
}
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// checks if check box is checked
if(holder.checkBox.isChecked()){
Toast.makeText(mCtx, "User is checked", Toast.LENGTH_SHORT).show();
}
else{
}
}
});
}
#Override
public int getItemCount() {
return mUsers.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
Admin admin;
CircleImageView profile_pic;
TextView username;
TextView last_msg;
CheckBox checkBox;
// status online or offline indicators
CircleImageView status_online;
CircleImageView status_offline;
public ViewHolder(View itemView) {
super(itemView);
profile_pic = itemView.findViewById(R.id.profile_image);
username = itemView.findViewById(R.id.username);
checkBox = itemView.findViewById(R.id.add_user);
status_online = itemView.findViewById(R.id.status_online);
status_offline = itemView.findViewById(R.id.status_offline);
last_msg = itemView.findViewById(R.id.last_msg);
}
}
// checks for last message
private void lastMessage(final String user_id, final TextView last_msg){
theLastMessage = "default";
// getting the uid of the admin stored in shared preference
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mCtx);
final String admin_uid = preferences.getString("uid","");
DatabaseReference lastMsgRef = FirebaseDatabase.getInstance().getReference("Chats");
lastMsgRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
Chats chats = snapshot.getValue(Chats.class);
assert chats != null;
// compares the uid of the admin and user and return the last message
if(chats.getReceiver().equals(admin_uid) && chats.getSender().equals(user_id)
|| chats.getReceiver().equals(user_id) && chats.getSender().equals(admin_uid)){
theLastMessage = chats.getMessage();
}
}
// switch case for theLastMessage
switch (theLastMessage){
case "default":
last_msg.setText(R.string.no_message);
break;
default:
last_msg.setText(theLastMessage);
break;
}
theLastMessage = "default";
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// display error message if one should occur
Toast.makeText(mCtx, databaseError.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
}
I put an arrow (like this <----) where you have to make changes to your code
public class RecyclerViewAdapterAddUsers extends RecyclerView.Adapter<RecyclerViewAdapterAddUsers.ViewHolder> {
Admin admin;
// variable to store admin uid from sharePreference
//String admin_uid;
private Context mCtx;
private List<Users> mUsers;
private boolean isChat;
// string variable to contain lastMessage from user
private String theLastMessage;
// strings to store the ids of chat users <--------------------------------------------
private List<String> selectedUsersIds;
//getter method
List<String> getUserIdsList(){
return selectedUsersIds;
}
public RecyclerViewAdapterAddUsers(Context mCtx, List<Users> mUsers, boolean isChat){
this.mCtx = mCtx;
this.mUsers = mUsers;
this.isChat = isChat;
selectedUsersIds = new ArrayList<String>(); // <--------------------------------------------
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_add_users,parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
// gets the positions of the all users
final Users users = mUsers.get(position);
// sets username to the text of the textView
holder.username.setText(users.getUsername());
if(users.getImageUrl() == null){
// loads the default placeholder into ImageView if ImageUrl is null
holder.profile_pic.setImageResource(R.drawable.ic_person_unknown);
}
else{
// loads users image into the ImageView
Glide.with(mCtx).load(users.getImageUrl()).into(holder.profile_pic);
}
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// checks if check box is checked
if(holder.checkBox.isChecked()){
Toast.makeText(mCtx, "User is checked", Toast.LENGTH_SHORT).show();
//add the user id to the list <--------------------------------------------
selectedUsersIds.add(users.getId()); // or whatever the method to get the user id name have <--------------------------------------------
}
else{
//remove the id if the user it's unchecked <--------------------------------------------
selectedUsersIds.remove(users.getId()); // <--------------------------------------------
}
}
});
}
#Override
public int getItemCount() {
return mUsers.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
Admin admin;
CircleImageView profile_pic;
TextView username;
TextView last_msg;
CheckBox checkBox;
// status online or offline indicators
CircleImageView status_online;
CircleImageView status_offline;
public ViewHolder(View itemView) {
super(itemView);
profile_pic = itemView.findViewById(R.id.profile_image);
username = itemView.findViewById(R.id.username);
checkBox = itemView.findViewById(R.id.add_user);
status_online = itemView.findViewById(R.id.status_online);
status_offline = itemView.findViewById(R.id.status_offline);
last_msg = itemView.findViewById(R.id.last_msg);
}
}
// checks for last message
private void lastMessage(final String user_id, final TextView last_msg){
theLastMessage = "default";
// getting the uid of the admin stored in shared preference
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mCtx);
final String admin_uid = preferences.getString("uid","");
DatabaseReference lastMsgRef = FirebaseDatabase.getInstance().getReference("Chats");
lastMsgRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
Chats chats = snapshot.getValue(Chats.class);
assert chats != null;
// compares the uid of the admin and user and return the last message
if(chats.getReceiver().equals(admin_uid) && chats.getSender().equals(user_id)
|| chats.getReceiver().equals(user_id) && chats.getSender().equals(admin_uid)){
theLastMessage = chats.getMessage();
}
}
// switch case for theLastMessage
switch (theLastMessage){
case "default":
last_msg.setText(R.string.no_message);
break;
default:
last_msg.setText(theLastMessage);
break;
}
theLastMessage = "default";
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// display error message if one should occur
Toast.makeText(mCtx, databaseError.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
}
then, in the class where you instantiate the adapter call the get method for the userIds list, something like this.
List<String> userIds = adapter.getUserIdsList();
That way you can do whatever you want with that list of selected userIds

Categories

Resources