Android: Firebase ChildEventListener() not working - android

I am working in my app with Firebase and I tried to use onChildAdded() callback but I think I am doing something wrong because I get no response.
/**
* Constructor
*/
private FirebaseManager(Context context) {
Firebase.setAndroidContext(context);
Firebase.getDefaultConfig().setPersistenceEnabled(true);
mFirebaseRef = new Firebase(FIREBASE_URL);
}
public void checkUsers() {
Firebase checkRef = mFirebaseRef.child("/data/users/");
// Also tried
// Firebase checkRef = mFirebaseRef.child("data").child("users");
checkRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.d(TAG,"New child added");
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
In onCreate() of my MainActivity I authenticate the user and the call checkUsers(). After that I manually add a new user in database. But I get nothing in log.
This is the json structure:
What am I doing wrong?

I got it. There was a concurrency problem. I called checkUsers() in onCreate() of the MainActivity but it needs to be called in onAuthenticated(), because the user was authenticated after the method checkUsers() tried to set listeners.
I got a LOG about the failure of accessing database:
W/SyncTree: Listen at / failed: FirebaseError: Permission denied
but didn't seen it because I was following a specific TAG with logcat Search.

Related

Firebase onchildadded() returns same data 3 times in listview

My problem is the same with title,firebase onchildadded() returns same data 3 times in listview.I tried many things but still couldnt found solution.
My code is there;
public void ReceiveMessages(){
childEventListener = message_dbref.child(user_id).child(user2_id).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Message message = dataSnapshot.getValue(Message.class);
message_dbref.removeEventListener(childEventListener);
user_dbref.removeEventListener(valueEventListener);
messageArrayList.add(message);
messageAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
So you should not be using a childEventListener because it fires whenever any child of the parent node changes.
You can check if you're updating other children of the parent node on which your childEventListener is set, along with others. That must be the case, for it to fire 3 times.
So you should rather focus on using a singleValueEventListener or a valueEventListener on the same reference you're using right now.
Read more about childEventListeners here.
Understand more about reading and writing on Firebase here.

Why onChildAdded is fired multiple times?

I have a problem with my code, I don't know if I get it because of onChildAdded or RecyclerView
Simply I want to display messages Inbox on RecyclerView that contains all messages I received from other users, each message contains the last message sent and information about senders such as his name and photo.
Like this
This is my structure
Messages
Receiver_UID
Sender_UID
push
message : "text"
I used 2 nested query to achieve that
so firstly I get sender UID, and then I get the last message from another query
dataQuery = FirebaseDatabase.getInstance().getReference("Messages").child(my_Id);
dataQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot getalldata, String s) {
final String sender_UID = getalldata.getKey();
Query lastmess = FirebaseDatabase.getInstance().getReference("Messages").child(my_Id).child(sendUID);
lastmess.orderByKey().limitToLast(1).addChildEventListener(new ChildEventListener() { // last message
#Override
public void onChildAdded(DataSnapshot snap, String s) {
MessModel messages = snap.getValue(MessModel.class);
String Last_message = messages.getMessage();
getUserData(Last_message ,sender_UID);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
And finally I get information of sender by this method
private void getUserData(final String last_message , String sendUID) {
FirebaseDatabase.getInstance().getReference("Users").orderByKey().equalTo(sendUID).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(final DataSnapshot data, final String s) {
listImessagesitem model = data.getValue(listImessagesitem.class);
name =model.getName();
uid = model.getUid();
//another information
result.add( new listImessagesitem( name ,last_message ,uid, ... another info));
useradapter = new listMessagesAdapter(getActivity(),result);
myList.setAdapter(useradapter);
useradapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
It works well the first time and when I make refresh as well
The problem is when someone, in the list of messages Inbox, sends me a new message. In this case, if I didn't make refresh, I see two senders with the same information and different last messages ... If he sent again, I see 3 senders with same previous case and so on.
How can I fix it?
I mean How can I add the new message to the user if he already exists in my inbox list
Any help would be appreciated, Thanks
What I understand from looking at your code is that u have nested ChildEventListener's. So every-time the top listener is invoked a new inner child listener is created causing duplicate data as it calls the getUserData method to update the adapter.
What you can do?
1: Check if the result list contains the object if not then add otherwise ignore.
2: From what I understand, I believe you are trying to create a Mail Client application where two users are sending emails to each other. So instead of the structure that you have in your db why not create a single node for both the users something like this user_1_ID+user_2_ID .
This reduces the complexity as both the users will read from the same node and the message object should have a timestamp field to determine the latest message.

How can I get value of this child?

It's not current id that user logged... it's other uid from other user when other user send a request.
From what I understand, you want to get to know whenever you receive a friend request. I see that you've created a Friend_req node and have each user's keys inside it. This is good. I assume that you do have a minimal grasp of Firebase and flattening of data.
With this assumption, my answer is that you need a childEventListener on the node that you need to track for friend requests. The childEventListener has a onChildAdded() method that downloads data whenever a new child is added to the code ( in your case, a new friend request ). Here's a basic implementation.
FirebaseDatabase.getInstance().getReference().child("Friend_req")
.child(yourUserKey).addChildEventListener(new ChildEventListener() {
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//Get notified on friend request
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Firebase return onAddChild

I am trying to return every dataSnapshot.getKey() in onAddchild to the main method to be used and back to this method to add a new child again, here is my code
private String NameSub(DataSnapshot dataSnapshot) {
RootRef.child(dataSnapshot.getKey()).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
NameSub = dataSnapshot.getKey();
Log.i("ttttttttttttttttttttt20", NameSub);
return;
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Log.i("ttttttttttttttttttttt21", String.valueOf(NameSub));
return NameSub;
}
I'm logging to trace the code and it's giving me Log"ttttttttttttttttttttt21" beftore Log"ttttttttttttttttttttt20". Also, giving me null value towards the 21 Logs.
How is it that the code is working, but it is printing Log 21 before Log 20? How can I fix that?
NB: I'm receiving no null value of dataSnapshot from another Firebase method
new ChildEventListener() { ... } is a callback.
When your function is called, this is what happens.
private String NameSub(DataSnapshot dataSnapshot) {
RootRef.child(dataSnapshot.getKey()).addChildEventListener(new ChildEventListener() { ... });
Log.i("ttttttttttttttttttttt21", String.valueOf(NameSub));
return NameSub;
}
So your function returns a null value.
Later whenever a child is added to your firebase realtime database, onChildAdded(...) is called.
This happens asynchronously. This updates the NameSub value.
So your code is printing Log 21 before Log 20.

Altering Firebase reference depending on whether a node has child or not before loading data

I am trying to set my Firebase reference before my child listener kicks in and loads my data. I know onCreate is ahead of onResume but my code below seems to contradict it as my reference is still what I have set in my onResume(). It seems like what I set up in onCreate doesn't go before what I have in onCreate().
Why is that?
I am trying to read from a template in my database if another node doesn't have the user registered as a child yet.
Any hint would be appreciated.
p.s. I have logged out the references and the Log in OnResume() goes first as well.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.services_activity);
app = FirebaseApp.getInstance();
database = FirebaseDatabase.getInstance(app);
auth = FirebaseAuth.getInstance(app);
storage = FirebaseStorage.getInstance(app);
username = auth.getCurrentUser().getUid();
databaseRef = database.getReference("serv_hst");
servTempltRef = database.getReference("serv_tmplt");
databaseRef.child(username).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//I am trying to set my reference that I will use in OnResume() ..!!
if (dataSnapshot.hasChildren()) {
servTempltRef = database.getReference("serv_hst");
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
protected void onResume() {
super.onResume();
servTempltRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The code inside the onChildAdded() will be executed asynchronously only when the data will be downloaded from Firebase Database.
So, after that the execution flow will execute the line in which there is the .addChildEventListener() method, it will go ahead and will continue to execute the next lines...
In your case, the onCreate() has no other lines to be executed. So, due to the Activity lifecicle, the onResume() method will be executed without the data you need.

Categories

Resources