Android chat crashes on DataSnapshot.getValue() - java

This is my first Firebase app and I am trying to retrieve a list of chat messages. The loop stops and I don't know why and how to fix it
The Error:
com.google.firebase.database.DatabaseException: Can't convert object
of type java.lang.String to type com.venomapps.amchat.Model.Chat
The Error is here
Chat chat = snapshot.getValue(Chat.class);
Error Function
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mchat.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Chat chat = snapshot.getValue(Chat.class);
if(chat.getReceiver().equals(myid) && chat.getSender().equals(userid) ||
chat.getReceiver().equals(userid) && chat.getSender().equals(myid)){
mchat.add(chat);
}
messageAdapter = new MessageAdapter(MessageActivity.this, mchat, imageurl);
recyclerView.setAdapter(messageAdapter);
}
}
Chat class
public class Chat {
private String sender;
private String receiver;
private String message;
public Chat(String sender, String receiver, String message) {
this.sender = sender;
this.receiver = receiver;
this.message = message;
}
public Chat() {
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Adapter
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHolder> {
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;
FirebaseUser fuser;
public MessageAdapter(Context mContext, List<Chat> mChat, String imageurl){
this.mChat = mChat;
this.mContext = mContext;
this.imageurl = imageurl;
}
#NonNull
#Override
public MessageAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == MSG_TYPE_RIGHT) {
View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_right, parent, false);
return new MessageAdapter.ViewHolder(view);
} else {
View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_left, parent, false);
return new MessageAdapter.ViewHolder(view);
}
}
#Override
public void onBindViewHolder(#NonNull MessageAdapter.ViewHolder holder, int position) {
Chat chat = mChat.get(position);
holder.show_message.setText(chat.getMessage());
if(imageurl.equals("default")){
holder.profile_image.setImageResource(R.mipmap.ic_launcher);
} else {
Glide.with(mContext).load(imageurl).into(holder.profile_image);
}
}
#Override
public int getItemCount() {
return mChat.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView show_message;
public ImageView profile_image;
public ViewHolder(View itemView){
super(itemView);
show_message = itemView.findViewById(R.id.show_message);
profile_image = itemView.findViewById(R.id.profile_image);
}
}
#Override
public int getItemViewType(int position) {
fuser = FirebaseAuth.getInstance().getCurrentUser();
if(mChat.get(position).getSender().equals(fuser.getUid())){
return MSG_TYPE_RIGHT;
} else {
return MSG_TYPE_LEFT;
}
}
}
Edit :
because i can't determine where is the problem
Structure Image
The Whole Message Activity
import de.hdodenhof.circleimageview.CircleImageView;
public class MessageActivity extends AppCompatActivity {
CircleImageView profile_image;
TextView username;
FirebaseUser fuser;
DatabaseReference reference;
ImageButton btn_send;
EditText text_send;
MessageAdapter messageAdapter;
List<Chat> mchat;
RecyclerView recyclerView;
Intent intent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message);
// Toolbar
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
// Recycler View
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
profile_image = findViewById(R.id.profile_image);
username = findViewById(R.id.username);
btn_send = findViewById(R.id.btn_send);
text_send = findViewById(R.id.text_send);
intent = getIntent();
final String userid = intent.getStringExtra("userid");
fuser = FirebaseAuth.getInstance().getCurrentUser();
btn_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String msg = text_send.getText().toString();
if(!msg.equals("")){
sendMessage(fuser.getUid(), userid, msg);
} else {
Toast.makeText(MessageActivity.this, "You can't send empty message", Toast.LENGTH_SHORT).show();
}
text_send.setText("");
}
});
reference = FirebaseDatabase.getInstance().getReference("Users").child(userid);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
username.setText(user.getUsername());
if(user.getImageURL().equals("default")){
profile_image.setImageResource(R.mipmap.ic_launcher);
} else {
Glide.with(MessageActivity.this).load(user.getImageURL()).into(profile_image);
}
readMessage(fuser.getUid(), userid, user.getImageURL());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void sendMessage(String sender, String receiver, String message){
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("sender", sender);
hashMap.put("receiver", receiver);
hashMap.put("message", message);
reference.child("Chats").push().setValue(hashMap);
}
private void readMessage(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);
if(chat.getReceiver().equals(myid) && chat.getSender().equals(userid) ||
chat.getReceiver().equals(userid) && chat.getSender().equals(myid)){
mchat.add(chat);
}
messageAdapter = new MessageAdapter(MessageActivity.this, mchat, imageurl);
recyclerView.setAdapter(messageAdapter);
}
} */
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mchat.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Chat chat = snapshot.getValue(Chat.class);
if(chat.getReceiver().equals(myid) && chat.getSender().equals(userid) ||
chat.getReceiver().equals(userid) && chat.getSender().equals(myid)){
mchat.add(chat);
}
messageAdapter = new MessageAdapter(MessageActivity.this, mchat, imageurl);
recyclerView.setAdapter(messageAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}

Good news, it's an easy fix.
The issue is that you're not pushing chat data properly in the picture below. Instead of having a path with several chats, you're just having 1 chat message.
The solution
Your database should look like this
The highlighted yellow keys are called push ids or push keys.
You are most likely saving your chat data like this:
FirebaseDatabase.getInstance().getReference().child("Chats").setValue(chatMessage);
You will accomplish what you want by adding in a push() before the setValue call.
FirebaseDatabase.getInstance().getReference().child("Chats").push().setValue(chatMessage);

Related

I want to get the qna list through firebase, but I can't get the list

This is a list of qna in the firebase. I want to print this out.
But my output list doesn't show anything.
https://i.stack.imgur.com/6ctRB.png
QNA Activity
public class QnaActivity extends AppCompatActivity {
private RecyclerView qnaRv;
private ArrayList<ModelQna> qnaList;
private AdapterQna adapterQna;
private ImageButton writeBtn;
private ImageButton backbtn;
private TextView tabQnaTv;
private RelativeLayout QnaRl;
private FirebaseAuth firebaseAuth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qna);
getSupportActionBar().hide();
qnaRv = findViewById(R.id.qnaRv);
tabQnaTv = findViewById(R.id.tabQnaTv);
QnaRl = findViewById(R.id.QnaRl);
backbtn = findViewById(R.id.backBtn);
writeBtn = findViewById(R.id.writeBtn);
firebaseAuth = FirebaseAuth.getInstance();
loadAllQna();
showQnaUI();
backbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
writeBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), AddQnaActivity.class);
startActivity(intent);
}
});
tabQnaTv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//load products
}
});
}
private void loadAllQna() {
qnaList = new ArrayList<>();
adapterQna = new AdapterQna(this, qnaList);
qnaRv.setAdapter(adapterQna);
//get all products
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Employees");
reference.child(firebaseAuth.getUid()).child("Qna").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
//before getting reset List
qnaList.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
ModelQna modelQna = dataSnapshot.getValue(ModelQna.class);
qnaList.add(modelQna);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseerror) {
}
});
}
private void showQnaUI() {
//show orders ui and hide products ui
QnaRl.setVisibility(View.GONE);
}
}
Model
public class ModelFaq {
private String faqId,faqTitle,faqContent, timestamp,uid,faqCategory;
public ModelFaq() {
}
public ModelFaq(String faqId, String faqTitle, String faqContent, String timestamp, String uid, String faqCategory) {
this.faqId = faqId;
this.faqTitle = faqTitle;
this.faqContent = faqContent;
this.timestamp = timestamp;
this.uid = uid;
this.faqCategory = faqCategory;
}
public String getFaqId() {
return faqId;
}
public void setFaqId(String faqId) {
this.faqId = faqId;
}
public String getFaqTitle() {
return faqTitle;
}
public void setFaqTitle(String faqTitle) {
this.faqTitle = faqTitle;
}
public String getFaqContent() {
return faqContent;
}
public void setFaqContent(String faqContent) {
this.faqContent = faqContent;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getFaqCategory() {
return faqCategory;
}
public void setFaqCategory(String faqCategory) {
this.faqCategory = faqCategory;
}
}
Qna Adapter
public class AdapterQna extends RecyclerView.Adapter<AdapterQna.HolderQna> {
private Context context;
public ArrayList<ModelQna> qnaList;
public AdapterQna(Context context, ArrayList<ModelQna> qnaList) {
this.context = context ;
this.qnaList = qnaList ;
}
#NonNull
#Override
public HolderQna onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//inflate layout
View view = LayoutInflater.from(context).inflate(R.layout.qna_item, parent, false);
return new HolderQna(view);
}
#Override
public void onBindViewHolder(#NonNull HolderQna holder, int position) {
ModelQna modelQna = qnaList.get(position);
String id = modelQna.getQnaId();
String uid = modelQna.getUid();
String qnaContent = modelQna.getQnaContent();
String qnaTitle = modelQna.getQnaTitle();
String timestamp = modelQna.getTimestamp();
//set data
holder.titleTextView.setText(qnaTitle);
holder.ContentTextView.setText(qnaContent);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//handle item clicks, show item details
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//handle item clicks, show item details
}
});
}
#Override
public int getItemCount() {
return qnaList.size();
}
class HolderQna extends RecyclerView.ViewHolder{
/*holds views of recyclerview*/
private TextView titleTextView, ContentTextView;
public HolderQna(#NonNull View itemView) {
super(itemView);
titleTextView = itemView.findViewById(R.id.item_post_title);
ContentTextView = itemView.findViewById(R.id.item_post_content);
}
}
}
Can you please change the code in your HolderQna to:
class HolderQna extends RecyclerView.ViewHolder{
/*holds views of recyclerview*/
private TextView titleTextView, ContentTextView;
public HolderQna(#NonNull View itemView) {
super(itemView);
titleTextView = itemView.findViewById(R.id.item_post_title);
ContentTextView = itemView.findViewById(R.id.item_post_content);
}
public void bind(qna: ModelQna){
titleTextView.setText(qna.qnaTitle);
ContentTextView.setText(qna.qnaContent);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//handle item clicks, show item details
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//handle item clicks, show item details
}
});
}
}
And your onBindViewHolder override of the AdapterQna to:
#Override
public void onBindViewHolder(#NonNull HolderQna holder, int position) {
ModelQna modelQna = qnaList.get(position);
String id = modelQna.getQnaId();
String uid = modelQna.getUid();
String qnaContent = modelQna.getQnaContent();
String qnaTitle = modelQna.getQnaTitle();
String timestamp = modelQna.getTimestamp();
//set data
holder.bind(modelQna);
}
Finally change your loadQna() function declaration as follows:
private void loadAllQna() {
qnaList = new ArrayList<>();
//get all products
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Employees");
reference.child(firebaseAuth.getUid()).child("Qna").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
//before getting reset List
qnaList.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
ModelQna modelQna = dataSnapshot.getValue(ModelQna.class);
qnaList.add(modelQna);
}
adapterQna = new AdapterQna(this, qnaList);
qnaRv.setAdapter(adapterQna);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseerror) {
Log.e("QnaActivity", databaseError.toString());
}
});
}
As far as I can see in your screenshot, the Qna node it's not nested under any UID, but directly under the Employees node. So when you attach a listener to the following node:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Employees");
reference.child(firebaseAuth.getUid()).child("Qna").addValueEventListener(/*...*/);
You will not be able to get any results, because such a reference doesn't exist. To solve this, you either create a reference that points exactly to "Qna":
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference qnaRef = db.child("Employees").child("Qna");
qnaRef.addValueEventListener(/*...*/);
Or you move the "Qna" node under the UID of the user, and leave the code unchanged.
Besides that, there is also another problem. The name of the fields in your ModelFaq class are different than the name of the properties in your database. You have in your ModelFaq class four fields called faqId, faqTitle, faqContent, faqCategory, all starting with faq while in the database I see that the names are different, qnaId, qnaTitle, qnaContent, qnaCategory, all are starting wiht qna, and this is not correct. So in order to be able to map a node into an object of type ModelFaq, the names must match. The only two fields that match are the timestamp and the uid.
In this case, you have two solutions. The first one would to change the name of your fieds in the ModelFaq class according to what it already exists in the database or you can use the PropertyName annotation in front of the getters like this:
#PropertyName("qnaId")
public String getFaqId() {
return faqId;
}

How do I sort recylerView items of recent conversation by time?

I'm basically building a chatting app, the home page shows RecyclerView items of users who are friends. My HomeActivity passes users of the User class to the adapter. The adapter takes each user info and current user info to look up the "chats" firebase database for the last message and last message time to show on the homepage items.
Homepage Items
As my User class doesn't have any field "last message time" I cannot compare one user to another for their last message time.
Now how do I compare the recycler view items to bring the latest message to the top?
User.Java
public class User {
private String userId, name, username, email, profileImage, token;
}
Message.Java
public class Message {
private String messageId, message, senderId, imageUrl;
private long timestamp;
private int feeling = -1;
}
Firebase database structure
chats -
CurrentUserID+ReceiverID
- lastMsg
- lastMsgTime
- messages
messageId
- message
- timestamp
HomeActivity.java
ArrayList<User> users; //declared above onCreate method
users = new ArrayList<>(); //onCreate method
homeAdapter = new HomeAdapter(this, users);
binding.homeRecyclerView.setAdapter(homeAdapter);
database.getReference().child("users").addValueEventListener(new ValueEventListener() {
#SuppressLint("NotifyDataSetChanged")
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
users.clear();
for (DataSnapshot snapshot1 : snapshot.getChildren()){
User user = snapshot1.getValue(User.class);
if(!user.getUserId().equals(mAuth.getUid())){
database.getReference().child("users")
.child(mAuth.getUid())
.child("friendList")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot snapshot2 : snapshot.getChildren()){
String check = String.valueOf(snapshot2.getValue());
if(check.equals(user.getUserId())){
Log.d("YESCheck", user.getUsername());
users.add(user);
}
}
Collections.sort(users, new Comparator<User>() {
#Override
public int compare(User user, User t1) {
return user.getName().compareToIgnoreCase(t1.getName());
}
});
homeAdapter.notifyDataSetChanged();
progressDialog.dismiss();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
HomeAdapter.java
public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.HomeViewHolder> {
FirebaseAuth mAuth;
FirebaseDatabase database;
Context context;
ArrayList<User> users;
String senderName;
public HomeAdapter(Context context, ArrayList<User> users) {
this.context = context;
this.users = users;
}
#NonNull
#Override
public HomeViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.activity_home_item, parent, false);
return new HomeViewHolder(view);
}
public void onBindViewHolder(#NonNull HomeViewHolder holder, int position) {
//HomeViewHolder viewHolder = (HomeViewHolder) holder;
User user = users.get(position);
mAuth = FirebaseAuth.getInstance();
database = FirebaseDatabase.getInstance();
String senderId = mAuth.getUid();
String senderRoom = senderId + user.getUserId();
holder.binding.friendName.setText(user.getName());
Picasso.get().load(user.getProfileImage()).into(holder.binding.friendProfilePic);
holder.binding.friend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, ChattingActivity.class);
intent.putExtra("userName", user.getName());
intent.putExtra("profilePic", user.getProfileImage());
intent.putExtra("userId", user.getUserId());
intent.putExtra("token", user.getToken());
//intent.putExtra("senderName", senderName);
context.startActivity(intent);
}
});
database.getReference().child("chats")
.child(senderRoom).addValueEventListener(new ValueEventListener() {
#SuppressLint("SetTextI18n")
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()){
String lastMsg = snapshot.child("lastMsg").getValue(String.class);
long time = snapshot.child("lastMsgTime").getValue(Long.class);
#SuppressLint("SimpleDateFormat")
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm a");
holder.binding.friendLastMsg.setText(lastMsg);
holder.binding.friendLastMsgTime.setText(dateFormat.format(new Date(time)));
}
else {
holder.binding.friendLastMsg.setText("Tap to chat");
holder.binding.friendLastMsgTime.setText("");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
#Override
public int getItemCount() {
return users.size();
}
#SuppressWarnings("InnerClassMayBeStatic")
protected class HomeViewHolder extends RecyclerView.ViewHolder {
ActivityHomeItemBinding binding;
public HomeViewHolder(#NonNull View view) {
super(view);
binding = ActivityHomeItemBinding.bind(view);
}
}
}

RecyclerView shows the same item many times in my app

I've created a match system in my Android program that also includes a chat section which has 2 fragments. The first fragment shows your chats, the second one shows your matches by using RecyclerView and UsersAdapter. However, in the second (match) fragment, people who you matched with are shown many times. For example, the same person is seen many times as you can see here.
My code is below.
UserFragment:
public class UsersFragment extends Fragment {
private RecyclerView recyclerView;
private UsersAdapter usersAdapter;
private List<User> mUsers;
FirebaseFirestore usersfragmentstore;
FirebaseAuth readauth;
DocumentReference readref;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
usersfragmentstore = FirebaseFirestore.getInstance();
readauth = FirebaseAuth.getInstance();
View view = inflater.inflate(R.layout.fragment_users, container, false);
readref = usersfragmentstore.collection("users").document(readauth.getCurrentUser().getUid());
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mUsers = new ArrayList<>();
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("users");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
readref.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
DocumentSnapshot shot = task.getResult();
List<String> matchedid2 = new ArrayList<>();
matchedid2 = (List<String>) shot.get("matchlist");
if (matchedid2.contains(snapshot.getKey())) {
User user = snapshot.getValue(User.class);
mUsers.add(user);
usersAdapter = new UsersAdapter(getContext(), mUsers, false);
recyclerView.setAdapter(usersAdapter);
}
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return view;
}
}
UserAdapter:
public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.ViewHolder> {
private Context mContext;
private List<User> mUsers;
private boolean ischat;
String theLastMessage;
public UsersAdapter(Context mContext, List<User> mUsers, boolean ischat) {
this.mUsers = mUsers;
this.mContext = mContext;
this.ischat = ischat;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.user_item_chat, parent, false);
return new UsersAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
User user = mUsers.get(position);
holder.username.setText(user.getName());
if (user.getImageURL().equals("default")) {
holder.profile_image.setImageResource(R.drawable.profilepicture);
} else {
Glide.with(mContext).load(user.getImageURL()).into(holder.profile_image);
}
if (ischat) {
lastMessage(user.getId(), holder.last_msg);
} else {
holder.last_msg.setVisibility(View.GONE);
}
if (ischat) {
if (user.getStatus().equals("online")) {
holder.img_on.setVisibility(View.VISIBLE);
holder.img_off.setVisibility(View.GONE);
} else {
holder.img_on.setVisibility(View.GONE);
holder.img_off.setVisibility(View.VISIBLE);
}
} else {
holder.img_on.setVisibility(View.GONE);
holder.img_off.setVisibility(View.GONE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext, MessageActivity.class);
intent.putExtra("userid", user.getId());
mContext.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return mUsers.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView username;
public ImageView profile_image;
private ImageView img_on;
private ImageView img_off;
private TextView last_msg;
public ViewHolder(#NonNull View itemView) {
super(itemView);
username = itemView.findViewById(R.id.chatusername);
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 = "defalut";
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Chats");
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();
}
}
}
switch (theLastMessage) {
case "default":
last_msg.setText("No message");
break;
default:
last_msg.setText(theLastMessage);
break;
}
theLastMessage = "default";
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
What am I missing?
befor adding new data first clear list by mUsers.clear(); as below
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
readref.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
DocumentSnapshot shot = task.getResult();
List<String> matchedid2 = new ArrayList<>();
matchedid2 = (List<String>) shot.get("matchlist");
if (matchedid2.contains(snapshot.getKey())) {
mUsers.clear();
User user = snapshot.getValue(User.class);
mUsers.add(user);
usersAdapter = new UsersAdapter(getContext(), mUsers, false);
recyclerView.setAdapter(usersAdapter);
}
}
});
}

How to make my recycler adapter retrieve messages sent to firebase database?

I cannot get the chats to display in the recycler adapter, I have already in firebase database and as well have attached firebase recycler adapter
I have tried some of the ways of getting the recycler adapter to display the chats but unable to display my adapter
private void DisplayReceiverInformation() {
receiverName.setText(messageReceiverName);
rootReference.child("Users").child(messageReceiverID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
//retrieve from db
final String userName = dataSnapshot.child("fullName").getValue().toString();
final String profileImage = dataSnapshot.child("profileImage").getValue().toString();
//set values
receiverName.setText(userName);
Picasso.get().load(profileImage).placeholder(R.drawable.profile_image_placeholder).into(receiverProfileImage);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
\\\
//initialize the above variables
private void InitializeFields() {
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//connect chat custom bar to chat activity
ActionBar actionBar = getSupportActionBar();
Objects.requireNonNull(actionBar).setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowCustomEnabled(true);
LayoutInflater layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View action_bar_view = layoutInflater.inflate(R.layout.chat_custom_toolbar, null);
actionBar.setCustomView(action_bar_view);
receiverName = findViewById(R.id.custom_profile_name);
receiverProfileImage = findViewById(R.id.custom_profile_image);
sendMessageButton = findViewById(R.id.send_message_button);
userMessageInput = findViewById(R.id.input_message);
// messageAdapter = new MessagesAdapter(ChatActivity.this,)
messageAdapter = new MessagesAdapter( messageList);
userMessagesList = (RecyclerView) findViewById(R.id.messages_list_of_users);
linearLayoutManager = new LinearLayoutManager(this);
userMessagesList.setHasFixedSize(true);
userMessagesList.setLayoutManager(linearLayoutManager);
userMessagesList.setAdapter(messageAdapter);
}
\\\
#Override
protected void onStart() {
super.onStart();
rootReference.child("Messages").child(messageSenderID).child(messageReceiverID)
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Messages messages = dataSnapshot.getValue(Messages.class);
messageList.add(messages);
messageAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
\\\
MessagesAdapter.java
package com.MwandoJrTechnologies.the_smart_parent.Chats;
public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MessageViewHolder> {
private List<Messages> userMessagesList;
private FirebaseAuth mAuth;
private DatabaseReference usersDatabaseReference;
public MessagesAdapter(List<Messages> userMessagesList) {
this.userMessagesList = userMessagesList;
}
public class MessageViewHolder extends RecyclerView.ViewHolder {
public TextView senderMessageText;
public TextView receiverMessageText;
public CircleImageView receiverProfileImage;
public MessageViewHolder(#NonNull View itemView) {
super(itemView);
senderMessageText = (TextView) itemView.findViewById(R.id.sender_message_text_view);
receiverMessageText = (TextView) itemView.findViewById(R.id.receiver_message_text_view);
receiverProfileImage = (CircleImageView) itemView.findViewById(R.id.receiver_message_profile_image);
}
}
#NonNull
#Override
public MessageViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.message_layout_of_users, parent, false);
mAuth = FirebaseAuth.getInstance();
return new MessageViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MessageViewHolder holder, int position) {
//get senders ID
String messageSenderID = mAuth.getCurrentUser().getUid();
Messages messages = userMessagesList.get(position);
//get ID of the receiver
String fromUserID = messages.getFrom();
//now get type of message whether text or image
String fromMessageType = messages.getType();
//retrieve receivers profile image
usersDatabaseReference = FirebaseDatabase.getInstance().getReference().child("Users").child(fromUserID);
usersDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("profileImage")){
String receiverImage = dataSnapshot.child("profileImage").getValue().toString();
Picasso.get().load(receiverImage).placeholder(R.drawable.profile_image_placeholder)
.into(holder.receiverProfileImage);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
if (fromMessageType.equals("text")){
holder.receiverMessageText.setVisibility(View.INVISIBLE);
holder.receiverProfileImage.setVisibility(View.INVISIBLE);
//display the message to the sender and to the receiver
//for the receiver
if (fromUserID.equals(messageSenderID)) {
holder.senderMessageText.setBackgroundResource(R.drawable.sender_text_message_background);
holder.senderMessageText.setTextColor(Color.WHITE);
holder.senderMessageText.setGravity(Gravity.LEFT);
holder.senderMessageText.setText(messages.getMessage());
//for receiver
} else {
holder.senderMessageText.setVisibility(View.INVISIBLE);
holder.receiverMessageText.setVisibility(View.VISIBLE);
holder.receiverProfileImage.setVisibility(View.VISIBLE);
holder.receiverMessageText.setBackgroundResource(R.drawable.receiver_text_message_background);
holder.receiverMessageText.setTextColor(Color.WHITE);
holder.receiverMessageText.setGravity(Gravity.LEFT);
holder.receiverMessageText.setText(messages.getMessage());
}
}
}
#Override
public int getItemCount() {
return userMessagesList.size();
}
}
/// my modal class
Messages.java
package com.MwandoJrTechnologies.the_smart_parent.Chats;
//modal class to retrieve messages
public class Messages {
public String date, time, type, message, from;
public Messages(){
//empty default constructor
}
//generate constructor with parameters
public Messages(String date, String time, String type, String message, String from) {
this.date = date;
this.time = time;
this.type = type;
this.message = message;
this.from = from;
}
//generate getter and setter
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
}
The above code does not give me any result in the FirebaseRecycler adapter yet I expect it to display in the FirebaseRecycler adapter
I think the answer is below.
private void DisplayReceiverInformation() {
receiverName.setText(messageReceiverName);
rootReference.child("Users").child(messageReceiverID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
//retrieve from db
final String userName = dataSnapshot.child("fullName").getValue().toString();
final String profileImage = dataSnapshot.child("profileImage").getValue().toString();
//set values
receiverName.setText(userName);
Picasso.get().load(profileImage).placeholder(R.drawable.profile_image_placeholder).into(receiverProfileImage);
messageAdapter = new MessagesAdapter( messageList);
userMessagesList = (RecyclerView) findViewById(R.id.messages_list_of_users);
linearLayoutManager = new LinearLayoutManager(this);
userMessagesList.setHasFixedSize(true);
userMessagesList.setLayoutManager(linearLayoutManager);
userMessagesList.setAdapter(messageAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
//here the data will be null so you must display data inside onDataChange() method.
}

Firebase retrieving data to customlistview [Android]

My Error:
E/UncaughtException: com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.stitch.fractions.Profile.userInfo.UserInformation
at com.google.android.gms.internal.zzamy.zze(Unknown Source)
at com.google.android.gms.internal.zzamy.zzb(Unknown Source)
at com.google.android.gms.internal.zzamy.zza(Unknown Source)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
at com.stitch.fractions.Scoreboard.activity.activity.ScoreboardActivity$1.onDataChange(ScoreboardActivity.java:49)
at com.google.firebase.database.Query$1.onDataChange(Unknown Source)
at com.google.android.gms.internal.zzajp.zza(Unknown Source)
at com.google.android.gms.internal.zzakp.zzcxi(Unknown Source)
at com.google.android.gms.internal.zzaks$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:743)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5546)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)
I/FA: Tag Manager is not found and thus will not be used
I/Process: Sending signal. PID: 22183 SIG: 9
Disconnected from the target VM, address: 'localhost:8604', transport: 'socket'
My Activity Class:
public class ScoreboardActivity extends AppCompatActivity {
private FirebaseAuth mAuth;
private DatabaseReference dbRef;
private ArrayList<UserInformation> mArrayUserInfo = new ArrayList<>();
private String userId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scoreboard);
mAuth = FirebaseAuth.getInstance();
userId = mAuth.getCurrentUser().getUid();
dbRef = FirebaseDatabase.getInstance().getReference();
displayData();
}
public void displayData() {
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot users : dataSnapshot.getChildren()) {
for (DataSnapshot user : users.getChildren()) {
if (user.getKey().equals(userId)) {
for (DataSnapshot sItem : user.getChildren()) {
if (!(sItem.getKey().equals("age"))) {
UserInformation scoreActivity = sItem.getValue(UserInformation.class);
mArrayUserInfo.add(scoreActivity);
ScoreAdapter sAdapter = new ScoreAdapter(getApplicationContext(), mArrayUserInfo);
ListView listScore = (ListView)findViewById(R.id.lvScore);
listScore.setAdapter(sAdapter);
}
}
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ScoreboardActivity.this, "Error Kid", Toast.LENGTH_SHORT).show();
}
});
}
}
Here is My Model Class:
public class UserInformation {
public String name;
public String age;
public String score;
public UserInformation() {
}
public UserInformation(String name, String age, String score) {
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
public String getScore(){
return score;
}
}
}
Here is how i Wrote to Database:
public class ProfileActivity extends AppCompatActivity {
private FirebaseAuth firebaseAuth;
private TextView mUserEmail, mUserScore;
private Button mBtnLogOut, mBtnSave, mBtnScore;
private EditText mEdtProfileName, mEdtProfileAge;
private DatabaseReference dbRefer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
initComponent();
getCurrentUser();
checkCurrentUser();
firebaseDatabase();
mBtnLogOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
firebaseAuth.signOut();
finish();
Intent back = new Intent(ProfileActivity.this, HomeActivity.class);
startActivity(back);
Toast.makeText(ProfileActivity.this, "Good Bye", Toast.LENGTH_SHORT).show();
}
});
mBtnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
saveUserInfor();
}
});
mBtnScore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent game = new Intent(ProfileActivity.this, ScoreboardActivity.class);
startActivity(game);
}
});
}
public void initComponent() {
mBtnLogOut = (Button) findViewById(R.id.btnOut);
mUserEmail = (TextView) findViewById(R.id.userEmail);
firebaseAuth = FirebaseAuth.getInstance();
mEdtProfileName = (EditText) findViewById(R.id.edtProfileName);
mEdtProfileAge = (EditText) findViewById(R.id.edtProfileAge);
mBtnSave = (Button) findViewById(R.id.btnSave);
mUserScore = (TextView) findViewById(R.id.userScore);
mBtnScore = (Button) findViewById(R.id.btnScore);
}
public void checkCurrentUser() {
firebaseAuth = FirebaseAuth.getInstance();
if (firebaseAuth.getCurrentUser() == null) {
finish();
Intent home = new Intent(ProfileActivity.this, HomeActivity.class);
startActivity(home);
}
}
public void getCurrentUser() {
FirebaseUser user = firebaseAuth.getCurrentUser();
mUserEmail.setText("Current User: " + user.getEmail());
}
public void firebaseDatabase() {
dbRefer = FirebaseDatabase.getInstance().getReference();
mEdtProfileName.getText().toString().trim();
mEdtProfileAge.getText().toString().trim();
}
public void saveUserInfor() {
String name = mEdtProfileName.getText().toString().trim();
String age = mEdtProfileAge.getText().toString().trim();
SharedPreferences prefsName = getSharedPreferences("Name", MODE_PRIVATE);
SharedPreferences.Editor editorName = prefsName.edit();
editorName.putString("sentname", name);
editorName.commit();
SharedPreferences prefsAge = getSharedPreferences("Age", MODE_PRIVATE);
SharedPreferences.Editor editorAge = prefsAge.edit();
editorAge.putString("sentage", age);
editorAge.commit();
SharedPreferences prefs = getSharedPreferences("Data",MODE_PRIVATE);
String data = prefs.getString("time","hi");
if (TextUtils.isEmpty(name)) {
mEdtProfileName.setError("Empty Field !!!");
return;
}
if (TextUtils.isEmpty(age)) {
mEdtProfileAge.setError("Empty Field !!!");
return;
}
UserInformation userInfo = new UserInformation(name, age, data);
FirebaseUser user = firebaseAuth.getCurrentUser();
dbRefer.child("User").child(user.getUid()).setValue(userInfo);
Toast.makeText(this, "Data Saved", Toast.LENGTH_SHORT).show();
}
}
My Adapter Class:
public class ScoreAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mScoreInflater;
private ArrayList<UserInformation> mUserInfo;
public ScoreAdapter(Context mContext, ArrayList<UserInformation> userInfo) {
this.mContext = mContext;
this.mScoreInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.mUserInfo = userInfo;
}
#Override
public int getCount() {
return mUserInfo.size();
}
#Override
public Object getItem(int position) {
return mUserInfo.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
classScoreHolder holder;
if (convertView == null) {
convertView = mScoreInflater.inflate(R.layout.scoreboard_row, parent, false);
holder = new classScoreHolder();
holder.mTvScoreName = (TextView) convertView.findViewById(R.id.tvScoreName);
holder.mTvScorePoint = (TextView) convertView.findViewById(R.id.tvScorePoint);
convertView.setTag(holder);
} else {
holder = (classScoreHolder) convertView.getTag();
}
TextView tvScoreName = holder.mTvScoreName;
TextView tvScorePoint = holder.mTvScorePoint;
UserInformation getUserInfo = (UserInformation) getItem(position);
tvScoreName.setText("User Name: " + getUserInfo.getName());
tvScorePoint.setText("User Score: " + getUserInfo.getScore());
return convertView;
}
private static class classScoreHolder {
public TextView mTvScoreName;
public TextView mTvScorePoint;
}
current database has name, age and score. What I'm trying to get is only Name and Age from Firebase Database into Customlistview.
Not 100% sure, but it look like you go one level too far in your hierarchy. If I am right, this would simplify your code. Try this :
public void displayData() {
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot users : dataSnapshot.getChildren()) {
for (DataSnapshot user : users.getChildren()) {
if (user.getKey().equals(userId)) {
UserInformation scoreActivity = user.getValue(UserInformation.class);
mArrayUserInfo.add(scoreActivity);
}
}
}
ScoreAdapter sAdapter = new ScoreAdapter(getApplicationContext(), mArrayUserInfo);
ListView listScore = (ListView)findViewById(R.id.lvScore);
listScore.setAdapter(sAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ScoreboardActivity.this, "Error Kid", Toast.LENGTH_SHORT).show();
}
});
}

Categories