In my application I try to call Notifications with the following code:
ref.orderByChild("uid").equalTo(uid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long number = dataSnapshot.getChildrenCount();
if (number == 0){
// no updates
return;
}
else {
showNotification();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
My problem is that Notifications are shown although there are no Updates in my Firebase-Database (especially for the retrieved Data). Why is the ValueEventListener running so often and how can I solve my issue? The 'number' is always the number of all assigned books from the logged-in User...
Maybe there is another smarter solution to get push-notifitcations.
Instead of addvalueeventlistener() use addListenerForSingleValueEvent
Related
I am trying send my contacts to firebase one by one and checking if the user is present or not but due to the asynchronous behavior of firebase some information is showing twice.
I want to synchronize this method like this:
loop send one number to firebase, firebase response, save, and continue
for (int i=0 ; i< list.size();i++) {
Check_Contact(list.get(i));
}
public void Check_Contact(String number)
{
DatabaseReference myRef = database.getReference("user").child(number);
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
}
else {
UserProfile row = dataSnapshot.getValue(UserProfile.class);
ls.add(row);
Adapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Can somebody tell me how to synchronize this method?
Firebase Structure
output coming
It is not the firebase async behaviour. You may have duplicate contents in your database. Please check ur database and update a screenshot of your database in your question.
It will be more helpful to understand your question.
I have some trouble trying to check if user information is stored already in the FireBase database.
Basically I'm trying to do something stupid like this:
"select user_name from user where user_id="+userID+"
And if the nickname exists it should make the boolean var isFirstTime = false and if it doesn't it should stay true. And after that it should show register box or not.
This is my db:
Firebase
And this is my code in onCreate method:
databaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference dbRefFirstTimeCheck = databaseReference.child("User").child(user.getUid()).child("Nickname");
isFirstTime = true;
dbRefFirstTimeCheck.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.getValue() != null) {
isFirstTime=false;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
if(isFirstTime) {
showNewUserBox();
}
else {
}
No matter what I do, the methor showNewUserBox() is being called. How do I get the data i need and check if it's there?
As others have commented, data is loaded from Firebase asynchronously. By the time you check isFirstTime, the data hasn't been loaded yet, onDataChange hasn't been run yet, so ifFirstTime will have its default value (false for a boolean).
All code that requires data from the database should be inside onDataChange (or invoked from within there). The simplest fix for your code is:
databaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference dbRefFirstTimeCheck = databaseReference.child("User").child(user.getUid()).child("Nickname");
dbRefFirstTimeCheck.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
showNewUserBox();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
Also see some of the many questions about asynchronous loading from Firebase, such as getContactsFromFirebase() method return an empty list (or this quite old classic: Setting Singleton property value in Firebase Listener).
I'm creating an Android app for the first time, I've got a simple Realtime Firebase Database with a couple of records in it. I have the following code;
public void onStart() {
super.onStart();
// Read from the database
databaseMatches.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot matchSnapshot : dataSnapshot.getChildren()) {
matches match = matchSnapshot.getValue(matches.class);
matchesList.add(match);
}
matchList adapter = new matchList (getActivity(), matchesList);
listViewMatch.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
If I put a breakpoint on the databaseMatches.addValueEventListener(new ValueEventListener() { it shows me that the database connection has been set and is returning the correct object (In my view).
The challenge I have is the part after, the break points for public void onDataChange nor onCancelled ever get hit. I'm lost here and not sure what might be the next step as it appears to be connecting, but I am not able to retrieve records.
I'm doing this in a fragment instead of a activity. Any help is appreciated.
Detecting Connection State
it is useful for your app to know when it is online or offline. Firebase Realtime Database provides a special location at /.info/connected which is updated every time the Firebase Realtime Database client's connection state changes. Here is an example: If you are not sure.
https://firebase.google.com/docs/database/android/offline-capabilities#section-connection-state
DatabaseReference connectedRef =
FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
System.out.println("connected");
} else {
System.out.println("not connected");
}
}
#Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled");
}
Firebase also loads and synchronizes data asynchronously
see Setting Singleton property value in Firebase Listener
Thanks.
There must have been some strange caching issue as the following morning when I ran the exact same code, no problem. And I've not had a problem since.
I have been trying to set a value change listener like this:
final DatabaseReference chat_ref =
FirebaseDatabase.getInstance().getReference(Constants.ARG_CHAT_ROOMS +
"/" + room_type_1);
chat_ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
showAlert(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The problem is that, the parenthesis after the showAlert method keeps looping over, creating several alerts when I only want one.
What could be causing this to loop and how can I address it?
Your help will be most appreciated!
I am not sure where I am getting it wrong, because even this loops as well:
chat_ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
showAlert(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You have those several alerts because of the way in which ValueEventListener works. But remember ValueEventListener is not a loop is an interface. Please see more details here. And as you see in the offical doc, it is triggered every time the data at a particular location changes.
To solve this, just get the call of the showAlert() out from the onDataChange method.
Hope it helps.
If you add ValueEventListener with addValueEventListener it will fire every time value of you reference changes so showAlert can be displayed several times.
Use addListenerForSingleValueEvent: your listener will be called only once.
https://firebase.google.com/docs/database/android/read-and-write#read_data_once
Within my app I often have the need to read data once. I originally started by using the addListenerForSingleValueEvent() method for this, however I ran into problems using this method as it does not work as I wanted when offline capabilities are enabled (see here the issue: Firebase Offline Capabilities and addListenerForSingleValueEvent)
In the question above it is mentioned that a workaround is to use the addValueEventListener() method, however I do not fully understand how to do this (particularly how to remove the ValueEventListener as soon I am finished grabbing the data I need).
Take this method which I created in a standalone class to query the Users node on Firebase where I store the users FCM Token. It seems to have an issue of not returning the latest token from the server everytime.
public class SendFCMMessage {
String userToken;
String currentUser;
String userName;
ValueEventListener userListener;
public void sendMessage(final String contactNumber) {
final DatabaseReference ref = FirebaseDatabase.getInstance().getReferenceFromUrl(link).child("Users").child(contactNumber);
userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
userToken = user.getToken();
// Send FCM Message after getting user token and then remove event listener
ref.removeEventListener(userListener);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("TAG", "Something terrible went wrong: " + databaseError);
}
};
ref.addValueEventListener(userListener);
}
}
If I remove the line
ref.removeEventListener(userListener);
Then this code works fine, however I would like to know how I could remove the ValueEventListener as soon as I receive the data I need?
Thanks,
R
ValueEventListener vel; //Declared Global
Listen your DatabaseReference like this;
vel = yourDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChanged(DataSnapshot dataSnapShot) {
//Do your stuff here. I suggest you create another method for this if you don't want a problem with inner class.
//For example, workDataSnapshot(DataSnapshot dataSnapShot) <-- Work here
yourDatabaseReference.removeEventListener(vel);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope it helps you.