I am trying to have an activity inside of my fragment, the fragment shows posts of people you follow and the activity shows the most recent post from anyone.
My fragment..
public class HomeFragment extends Fragment {
private PostAdapter postAdapter;
private List<Post> postLists;
private List<String> followingList;
private ProgressBar progressBar;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_home, container,false);
RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(getContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
postLists=new ArrayList<>();
postAdapter=new PostAdapter(getContext(), postLists);
recyclerView.setAdapter(postAdapter);
ImageView globalPosts = view.findViewById(R.id.globalPosts);
globalPosts.setOnClickListener(v->{
Intent intent= new Intent(getContext(), GlobalPostsActivity.class);
startActivity(intent);
});
progressBar=view.findViewById(R.id.progress_circular);
checkFollowing();
return view;
}
private void checkFollowing(){
followingList=new ArrayList<>();
DatabaseReference reference=FirebaseDatabase.getInstance().getReference("Support")
.child(Objects.requireNonNull(FirebaseAuth.getInstance().getCurrentUser()).getUid())
.child("supporting");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
followingList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
followingList.add(snapshot.getKey());
}
readPosts();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void readPosts(){
DatabaseReference reference= FirebaseDatabase.getInstance().getReference("Posts");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
postLists.clear();
for (DataSnapshot snapshot :dataSnapshot.getChildren()){
Post post=snapshot.getValue(Post.class);
for (String id: followingList){
assert post != null;
if (post.getPublisher().equals(id)){
postLists.add(post);
}
}
}
postAdapter.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
My activity..
public class GlobalPostsActivity extends AppCompatActivity {
private PostAdapter postAdapter;
private List<Post> postLists;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_global_posts);
RecyclerView recyclerView = findViewById(R.id.recycler_view1);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
postLists=new ArrayList<>();
postAdapter=new PostAdapter(this, postLists);
recyclerView.setAdapter(postAdapter);
readGlobalPosts();
}
private void readGlobalPosts(){
DatabaseReference reference= FirebaseDatabase.getInstance().getReference("Posts");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
postLists.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Post post=snapshot.getValue(Post.class);
assert post !=null;
postLists.add(post);
}
postAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
I get a fatal exception: main and my app crashes when i click on a users name to go to their profile. I am not sure why this is happening so any help is greatly appreciated.
There is one bit of your code I can see that will crash if asserts are enabled:
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Post post=snapshot.getValue(Post.class);
assert post !=null; // THIS
postLists.add(post);
}
What you have written there is the equivalent of:
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Post post=snapshot.getValue(Post.class);
if(post == null) {
throw new IllegalStateException("Post was null");
}
postLists.add(post);
}
and I am sure you don't want to crash your whole app when there is no Post?
If you want to test if it exists (and get feedback if it doesn't), try something like this:
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Post post=snapshot.getValue(Post.class);
if(post == null) {
Log.w("TUT", "Expected a post and didn't get one.");
} else {
postLists.add(post);
}
}
Ref:
https://en.wikibooks.org/wiki/Java_Programming/Keywords/assert
How to use assert in android?
Related
I'm creating a chat app and I imported this 3-year-old project so a lot of things have changed, especially this thing that I can't fix could anyone help me? Thanks.
The error that gives me:
'updateToken(java.lang.String)' in 'com.koddev.chatapp.Fragments.ChatsFragment' cannot be applied to '(com.google.android.gms.tasks.Task<java.lang.String>)'
public class ChatsFragment extends Fragment {
private RecyclerView recyclerView;
private UserAdapter userAdapter;
private List<User> mUsers;
FirebaseUser fuser;
DatabaseReference reference;
private List<Chatlist> usersList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chats, container, false);
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
fuser = FirebaseAuth.getInstance().getCurrentUser();
usersList = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser.getUid());
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
usersList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Chatlist chatlist = snapshot.getValue(Chatlist.class);
usersList.add(chatlist);
}
chatList();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
updateToken(FirebaseMessaging.getInstance().getToken());
return view;
}
private void updateToken(String token){
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Tokens");
Token token1 = new Token(token);
reference.child(fuser.getUid()).setValue(token1);
}
private void chatList() {
mUsers = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("Users");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mUsers.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
User user = snapshot.getValue(User.class);
for (Chatlist chatlist : usersList){
if (user.getId().equals(chatlist.getId())){
mUsers.add(user);
}
}
}
userAdapter = new UserAdapter(getContext(), mUsers, true);
recyclerView.setAdapter(userAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
You're getting the following error:
'updateToken(java.lang.String)' in 'com.koddev.chatapp.Fragments.ChatsFragment' cannot be applied to '(com.google.android.gms.tasks.Task<java.lang.String>)'
Because you're calling the updateToken() method with a wrong argument. You defined the method to take a String argument, while you're calling it with a Task object, hence the error. If you want to get the token and call the method correctly, please use the following lines of code:
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
#Override
public void onComplete(#NonNull Task<String> task) {
if (task.isSuccessful()) {
String token = task.getResult();
updateToken(token);
Log.d("TAG", token); //Check the generated token.
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
In my firebase I have questions and their answers stored. Each answer has an id, which it got from push(). But I am unable to show the list of all the users who have answered the question. Please help.
Here is the code:
ListView listView;
ArrayList<String> answerers = new ArrayList<>();
ArrayAdapter arrayAdapter;
String askedBy, question, likes;
FirebaseAuth mAuth;
DatabaseReference databaseReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_answers);
listView = findViewById(R.id.answersListView);
Intent intent = getIntent();
askedBy = intent.getStringExtra("askedBy");
question = intent.getStringExtra("question");
likes = intent.getStringExtra("numberOfLikes");
mAuth = FirebaseAuth.getInstance();
databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.child("questions").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()){
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
if (dataSnapshot.child("question").getValue().toString().equals(question) && dataSnapshot.child("askedBy").getValue().toString().equals(askedBy)
&& dataSnapshot.child("likes").getValue().toString().equals(likes)) {
dataSnapshot.child("answers").getRef().addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshots) {
if (snapshots.exists()){
for (DataSnapshot dataSnapshots : snapshots.getChildren()){
String id = dataSnapshot.getRef().push().getKey();
answerers.add(dataSnapshots.child(id).child("answeredBy").getValue().toString());
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
arrayAdapter = new ArrayAdapter<>(ViewAnswersActivity.this, android.R.layout.simple_list_item_1, answerers);
listView.setAdapter(arrayAdapter);
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent1 = new Intent(ViewAnswersActivity.this, AnswerActivity.class);
intent1.putExtra("askedBy", askedBy);
intent1.putExtra("answeredBy", answerers.get(i));
intent1.putExtra("question", question);
intent1.putExtra("numberOfLikes", likes);
startActivity(intent1);
}
});
}
When I am running the app, the listView is coming empty, indicating value hasn't been stored.
Try to set adapter within onDataChange()
#Override
public void onDataChange(#NonNull DataSnapshot snapshots) {
if (snapshots.exists()){
for (DataSnapshot dataSnapshots : snapshots.getChildren()){
String id = dataSnapshot.getRef().push().getKey();
answerers.add(dataSnapshots.child(id).child("answeredBy").getValue().toString());
}
arrayAdapter = new ArrayAdapter<> (ViewAnswersActivity.this, android.R.layout.simple_list_item_1, answerers);
listView.setAdapter(arrayAdapter);
}
}
I am trying to implement an SwipeRefreshLayout into my app. What I want to happen is that when the user opens the app initially that the data is retrieved from Firebase without having to pull down the layout so the data refreshes. After that, if the user wants to see new data they have to pull down the layout so the RecyclerView is refreshed with new posts that other users have uploaded.
The problem that I am running into is that when I upload a post from my emulator it pops up on screen automatically on my phone without me having to pull down. That's not what I want. First, initial opening of app data should be retrieved automatically without pull down. After that, every time you want to see new data, if I go to a different fragment and then come back the data shouldn't be refreshed unless I pull down.
The code that I have currently is the following. Can someone tell me why it isn't working the way that I would like it to?
I am relatively sure that it's because of my notifyDataSetChanged(); in my readPosts(); method, but I'm not sure how to fix it... Should I just remove it from readPosts(); and add it to the mSwipeRefreshLayout.post...Runnable?
HomeFragment
public class HomeTabLayoutFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private ProgressBar mProgressBar;
private PostAdapter mPostAdapter;
private List<Post> mPostLists;
private FirebaseAuth mFirebaseAuth;
private FirebaseUser mFirebaseUser;
private List<String> mFollowingList;
private SwipeRefreshLayout mSwipeRefreshLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home_tab_layout, container, false);
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
mProgressBar = v.findViewById(R.id.progress_circular);
RecyclerView recyclerView = v.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
mPostLists = new ArrayList<>();
mPostAdapter = new PostAdapter(getContext(), mPostLists);
recyclerView.setAdapter(mPostAdapter);
mSwipeRefreshLayout = v.findViewById(R.id.refresh);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.post(() -> {
mSwipeRefreshLayout.setRefreshing(true);
readPosts();
});
checkIfUserExists();
checkFollowing();
return v;
}
#Override
public void onRefresh() {
readPosts();
}
private void checkIfUserExists() {
if (mFirebaseAuth == null) {
Intent intent = new Intent(getContext(), RegisterActivity.class);
startActivity(intent);
}
}
private void checkFollowing() {
mFollowingList = new ArrayList<>();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Follow").child(mFirebaseUser.getUid()).child("Following");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mFollowingList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
mFollowingList.add(snapshot.getKey());
}
readPosts();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void readPosts() {
mSwipeRefreshLayout.setRefreshing(true);
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPostLists.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
if (post != null && shouldAddPost(post)) {
mPostLists.add(post);
}
}
mPostAdapter.notifyDataSetChanged();
mProgressBar.setVisibility(View.GONE);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
mSwipeRefreshLayout.setRefreshing(false);
}
private boolean shouldAddPost(#NotNull Post post) {
boolean isFollowingPublisher = false;
for (String id : mFollowingList) {
if (post.getPublisher().equals(id)) {
isFollowingPublisher = true;
break;
}
}
boolean isPublisher = post.getPublisher().equals(mFirebaseUser.getUid());
return isFollowingPublisher || isPublisher;
}
}
That is because you are using a addValueEventListener. In this case a ValueEventListener will get called each time any changes made in this hierarchy.
You should be using addListenerForSingleValueEvent if you want data only once. In other words if you do not want realtime updates for a node then you use addListenerForSingleValueEvent.
->Answer about mSwipeRefreshLayout.setRefreshing(false) positioning inside readPost .
Right now how you added mSwipeRefreshLayout.setRefreshing(true) and mSwipeRefreshLayout.setRefreshing(false) is actually useless . It will call immediately.. What you should be doing is changing the state inside listeners.
private void readPosts() {
mSwipeRefreshLayout.setRefreshing(true);
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPostLists.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
if (post != null && shouldAddPost(post)) {
mPostLists.add(post);
}
}
mPostAdapter.notifyDataSetChanged();
mProgressBar.setVisibility(View.GONE);
mSwipeRefreshLayout.setRefreshing(false);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
mSwipeRefreshLayout.setRefreshing(false);
}
});
I have the following problem. Posts of other users are coming out fine only one post. But if it's your profile, in the HomeFragment the posts are coming out duplicated and I am not sure why that is.
In my readPosts(); method, if I get rid of this line } else if (mFirebaseUser.getUid().equals(post.getPublisher())) {mPostLists.add(post); it's fine, but then my posts don't show up only the posts of the people I follow. I need mine to show up also in the newsfeed, but just once not duplicated. All of my posts are being duplicated. Same post comes up twice on my feed. Can someone tell me what I am doing wrong?
Something I am doing wrong in my readPosts(); method, but I am not sure what after having played around with it a bunch.
HomeFragment
public class HomeTabLayoutFragment extends Fragment {
private ProgressBar mProgressBar;
private PostAdapter mPostAdapter;
private List<Post> mPostLists;
private FirebaseAuth mFirebaseAuth;
private FirebaseUser mFirebaseUser;
private List<String> mFollowingList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home_tab_layout, container, false);
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
mProgressBar = v.findViewById(R.id.progress_circular);
RecyclerView recyclerView = v.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
mPostLists = new ArrayList<>();
mPostAdapter = new PostAdapter(getContext(), mPostLists);
recyclerView.setAdapter(mPostAdapter);
SwipeRefreshLayout refreshLayout = v.findViewById(R.id.refresh);
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
refreshLayout.setRefreshing(false);
}
});
checkIfUserExists();
checkFollowing();
return v;
}
private void checkIfUserExists() {
if (mFirebaseAuth == null) {
Intent intent = new Intent(getContext(), RegisterActivity.class);
startActivity(intent);
}
}
private void checkFollowing() {
mFollowingList = new ArrayList<>();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Follow").child(mFirebaseAuth.getCurrentUser().getUid()).child("Following");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mFollowingList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
mFollowingList.add(snapshot.getKey());
}
readPosts();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void readPosts() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPostLists.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
for (String id : mFollowingList) {
if (post != null) {
if (post.getPublisher().equals(id)) {
mPostLists.add(post);
} else if (mFirebaseUser.getUid().equals(post.getPublisher())) {
mPostLists.add(post);
}
}
}
mPostAdapter.notifyDataSetChanged();
mProgressBar.setVisibility(View.GONE);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Check your inner loop in readPosts(). The loop is based on elements of mFollowingList. This condition has nothing to do with that:
if (mFirebaseUser.getUid().equals(post.getPublisher()))
It will be either true or false for every execution of the internal loop. Therefore, it may add more elements than you want. You probably want to put it in the outer loop, not the inner one - to execute it just once per post.
I'd make some more changes though. The check (post != null) can be done outside the loop. No need to let it loop multiple times for no reason. notifyDataSetChanged() also does not need to be inside any loop, it needs to be called once.
Extra regarding code style :-) - You're using too much indentation. It makes sense to extract things to a separate method for readability, it's a good idea to keep methods short, with descriptive names.
private void readPosts() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPostLists.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
if (post != null && shouldAddPost(post)) {
mPostLists.add(post);
}
}
mPostAdapter.notifyDataSetChanged();
mProgressBar.setVisibility(View.GONE);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private boolean shouldAddPost(#NotNull Post post) {
boolean isFollowingPublisher = false;
for (String id : mFollowingList) {
if (post.getPublisher().equals(id)) {
isFollowingPublisher = true;
}
}
boolean isPublisher = post.getPublisher().equals(mFirebaseUser.getUid());
return isFollowingPublisher || isPublisher;
}
private void readPosts() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPostLists.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
for (String id : mFollowingList) {
if (post != null) {
if (post.getPublisher().equals(id)) {
mPostLists.add(post);
}
}
}
if (post != null)
if (mFirebaseUser.getUid().equals(post.getPublisher())) {
mPostLists.add(post);
}
}
mPostAdapter.notifyDataSetChanged();
mProgressBar.setVisibility(View.GONE);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
I'm building a simple chat application. In user fragment, if we click on user it get crashed and go to previous activity if there is previous chat. While there is no chat with that user fragment works fine, but when we type message and click send message store on Firebase and app crashes, similarly if there is chat, chat fragment get crashed.
I think problem is in mReference.addValueEventListener(new ValueEventListener()) method. Code and error is given below. I saw other answers but didn't understand with my code.
MessageActivity.java
public class MessageActivity extends AppCompatActivity {
CircleImageView profile_image;
TextView username;
FirebaseUser mFirebaseUser;
DatabaseReference mDatabaseReference;
ImageView btn_send;
EditText send_msg;
Intent mIntent;
MessageAdapter mMessageAdapter;
List<Chat> mChats;
RecyclerView mRecyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
profile_image = findViewById(R.id.profile_image);
username = findViewById(R.id.username);
btn_send = findViewById(R.id.img_btn_send);
send_msg = findViewById(R.id.text_send);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.setStackFromEnd(true);
mRecyclerView.setLayoutManager(linearLayoutManager);
mIntent = getIntent();
final String userid = mIntent.getStringExtra("userid");
mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
mDatabaseReference = FirebaseDatabase.getInstance().getReference("Users").child(userid);
btn_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String msg = send_msg.getText().toString();
if (!msg.equals("")){
sendMessage(mFirebaseUser.getUid(), userid, msg);
}
send_msg.setText("");
}
});
mDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
assert user != null;
username.setText(user.getUsername());
if ( user.getImageURL().equals("default")){
profile_image.setImageResource(R.mipmap.ic_launcher_round);
}else {
Glide.with(MessageActivity.this).load(user.getImageURL()).into(profile_image);
}
readMessage(mFirebaseUser.getUid(), userid, user.getImageURL());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void sendMessage(String sender, String receiver, String message){
DatabaseReference mDatabaseReference = FirebaseDatabase.getInstance().getReference();
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("sender", sender);
hashMap.put("receiver", receiver);
hashMap.put("message", message);
mDatabaseReference.child("Chats").setValue(hashMap);
}
private void readMessage(final String myId, final String userID, final String imageURL){
mChats = new ArrayList<>();
mDatabaseReference = FirebaseDatabase.getInstance().getReference("Chats");
mDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mChats.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){
Chat chat = dataSnapshot1.getValue(Chat.class);
assert chat != null;
if (chat.getReceiver().equals(myId) && chat.getSender().equals(userID) || chat.getReceiver().equals(userID) && chat.getSender().equals(myId)){
mChats.add(chat);
}
mMessageAdapter = new MessageAdapter(MessageActivity.this, mChats, imageURL);
mRecyclerView.setAdapter(mMessageAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
ChatsFragment.java
public class ChatsFragment extends Fragment {
private RecyclerView mRecyclerView;
private UserAdapter mUserAdapter;
private List<User> mUsers;
FirebaseUser fUser;
DatabaseReference mReference;
private List<String> userList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chats, container, false);
mRecyclerView = view.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
fUser = FirebaseAuth.getInstance().getCurrentUser();
userList = new ArrayList<>();
mReference = FirebaseDatabase.getInstance().getReference("Chats");
mReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
userList.clear();
for (DataSnapshot snapshot: dataSnapshot.getChildren()){
Chat chat = snapshot.getValue(Chat.class);
if (chat.getSender().equals(fUser.getUid())){
userList.add(chat.getReceiver());
}
if (chat.getReceiver().equals(fUser.getUid())){
userList.add(chat.getSender());
}
}
readChats();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return view;
}
private void readChats() {
mUsers = new ArrayList<>();
mReference = FirebaseDatabase.getInstance().getReference("Users");
mReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mUsers.clear();
for (DataSnapshot snapshot: dataSnapshot.getChildren()){
User user = snapshot.getValue(User.class);
for (String id : userList){
if (user.getId().equals(id)){
if (mUsers.size() != 0){
for ( User user1 : mUsers){
if ( !user.getId().equals(user1.getId()));
mUsers.add(user);
}
}
else{
mUsers.add(user);
}
}
}
}
mUserAdapter = new UserAdapter(getContext(), mUsers);
mRecyclerView.setAdapter(mUserAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Error is :
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database##16.0.4:423)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database##16.0.4:214)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database##16.0.4:79)
at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database##16.0.4:212)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database##16.0.4:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database##16.0.4:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database##16.0.4:55)
at android.os.Handler.handleCallback(Handler.java:754)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6228)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)