Im using the Android SDK for firebase database.
In the database I have a structure where I keep the messages ordered by user, that way if I need their messages I just query by user.
myDatabase -> messages -> JonDoe
-> "You forgot your mail"
-> "Buy groceries"
-> JaneDoe
-> "Dog's birthday!"
The problem is if the user doesnt exist the listener keeps waiting forever, and I want to show "You have no messages" in that case. (For example, if I query the user "CharlesDoe" in the example above)
Is there a way to check if a reference exists before/after/during a query?
try this:
DatabaseReference root =FirebaseDatabase.getInstance().getReference();
DatabaseReference user = root.child("myDatabase").child("messages");
user.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.child("CharlesDoe").exists()) {
// run some code
}else{
Toast.makeText(this,"no messages",Toast.Length_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here it will query on node messages and then it will check if the child exists and do the required.
Try this on
DatabaseReference root =FirebaseDatabase.getInstance().getReference();
DatabaseReference user =
root.child("myDatabase").child("messages").child("CharlesDoe");
user.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()) {
// run some code
}else{
Toast.makeText(this,"no messages",Toast.Length_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Related
I'm trying to get the "bet" collection from the firebase database (on android studio, using java).
this is the collection
pic1
pic2
,I got User class that has the fields
"full_name","email","password".
what should i do with the "bet" collection?
I tried
reference = FirebaseDatabase.getInstance().getReference().child("Users");
db = FirebaseFirestore.getInstance();
db.collection("Users").document(UserID).get().addOnCompleteListener(task ->{
if(task.isSuccessful() && task.getResult() != null){
String number_bet = task.getResult().getString("bet");
}
} );
It failed and i couldn't find any solutions
,I can access the other fields, for example
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
User user1 = snapshot.getValue(User.class);
if(user1 != null){
user_submit.setText(user1.bet_display);
}
}
all that i need is to get the drawn number (0-36) value(in that case String)
thanks!
that worked for me.
DatabaseReference reference=FirebaseDatabase.getInstance().getReference().child("Users");
reference.child(UserID).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String str2 = snapshot.child("bet").child(""+NUMBER).getValue().toString(); }
}
#Override
public void onCancelled(#NonNull DatabaseError error) { }
});
NUMBER is the path, it drawn every time..
just got to the right path by snapshot.child(some key).child(some key)....getValue().toString()
My Firebase Realtime Database has been built by loading an object of the Java class HashMap. In my Android Studio app I'm trying to write a method that takes a String (the key) as input, searches through the database and if the string is found it returns the associated Float (the value), otherwise it returns 0. How can I do this? Any help would be really appreciated!
EDIT: I've tried to follow the suggestions, adapting them to my particular case, but I didn't manage to solve the problem yet.
I wrote the following code in MainActivity:
DatabaseReference myRef;
Float tempValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
myRef = FirebaseDatabase.getInstance().getReference("myRoot");
tempValue=0f;
...
}
public void retrieveValueFromDatabase(String childName, final MainActivity activity){
myRef.child(childName).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Float value=dataSnapshot.getValue(Float.class);
if (value==null){
value=0f;
}
activity.tempValue=value;
//First Toast
//Toast.makeText(activity,"tempValue = "+tempValue.toString(), Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
public void useValues(){
retrieveValueFromDatabase(childName,this);
//Second Toast
//Toast.makeText(this,"tempValue = "+tempValue.toString(), Toast.LENGTH_LONG).show();
//code using tempValue from here
...
}
If I uncomment the first toast, the correct value inside tempValue is shown, but if I uncomment the second toast, the value of tempValue shown is the default one (0.0). What am I missing?
You need to use addValueEventListener to retrieve data from the database:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("myRoot").orderByChild("name").equalTo("peter");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i("Database", dataSnapshot.child("floatValue").getValue(Long.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})
Here, you add a reference to the root node, then query using equalTo() to check if name = peter exists in the database and return the float value.
You should read the guide:
https://firebase.google.com/docs/database/android/read-and-write
I am developing a chat app but when it comes to viewing friend requests to the user i face a problem that is
When I log queries of Firebase why is it not properly ordered as code ?
This is my code:
// Query for pending requests in the current user
Log.v("AAAAAA", "AAAAAA");
usersRef.child(MainActivity.currentUser.getUid()).child("inpendingfriendreq").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) { // dataSnapShot = inpendingfriendreq node
for (DataSnapshot reqDataSnapShot : dataSnapshot.getChildren()) {
U = reqDataSnapShot;
Log.v("BBBBBBBB", U.toString());
usersRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot sDataSnapshot) { // sDataSnapshot = "users" node DataSnapShot
for (DataSnapshot searchForPendingUserDS : sDataSnapshot.getChildren()) { // searchForPendingUserDS = a user from database (child node of "users" node)
Log.v("CCCCCCC", searchForPendingUserDS.toString());
if (searchForPendingUserDS.getKey().equals(U.getKey())) { // If that user's id equals pending req id
MainActivity.reqArrList.add(new FriendRequest(R.drawable.default_pp, searchForPendingUserDS.child("name").getValue(String.class)));
Log.v("DDDDDDDDD", searchForPendingUserDS.child("name").getValue(String.class));
}
}
Log.v("EEEEEEEE", MainActivity.reqArrList.toString());
//requestsPageUpdated();
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(mContext, "Error querying", Toast.LENGTH_SHORT).show();
}
});
//requestsPageUpdated();
Log.v("FFFFFFFFFF", "FFFFFFFFF");
break;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(mContext, "Error querying", Toast.LENGTH_SHORT).show();
}
});
It should be:
AAAAAA
BBBBBB
CCCCCC
DDDDDD
CCCCCC
CCCCCC
CCCCCC
EEEEEE
FFFFFF
GGGGGG
But it shows that in the Logcat:
AAAAAA
GGGGGG
BBBBBB
FFFFFF
CCCCCC
DDDDDD
CCCCCC
CCCCCC
CCCCCC
EEEEEE
I know that event listeners are Async but what is the meaning of that ?
Does Async means that the function are waiting to be triggered like Button onClickListener or does it mean that when it's triggered it runs parallel to the main thread? so in the second case that will make sense to my problem.
Any help, please!
I have a Firebase database that I want to retrieve the friend ID from. This works perfectly as I'm getting the right value when logging the friendUserId in the for loop. However, the log at the end of the method only displays the right value after executing the method twice. At first it displays "s", the second time it displays the string that I want. I feel like it has got something to do with processing time of the query, but I'm not sure really. How do I solve this?
public String friendUserId="s";
public void checkUserExistence() {
mDatabase.child("Users")
.orderByChild("username")
.equalTo(EmailSearchQuery)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
friendUserId = childSnapshot.getKey();
Log.d("dwada",friendUserId);
}
} else
Toast.makeText(AddAFriend.this, "Gebruiker niet gevonden", Toast.LENGTH_LONG);
}
#Override
public void onCancelled(DatabaseError firebaseError) {
Log.e("MainActivity", "onCancelled", firebaseError.toException());
}
});
Log.d("dwada",friendUserId);
}
for example searching in circles for a user circle if a data exist I want it DO process 1 and if data doesn't exist I want it to create one then DO process 2 ... but what happens in this code if data doesn't exist it will create one then do process 2 then go back then do process 1 after checking. so how can I stop the listener after process 2.
sorry if the circles example is too ambiguous but this is the simplest example I could think of .
Firebase ref= new Firebase("https://XXXXX.firebaseio.com/circles/");
Query queryRef = ref.orderByChild("circalename").equalTo(user.circalename);
ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot datasnapshot) {
if (datasnapshot.exists()) { // I don't want to get back here after
//creating the data in the else statement
// DO process 1
}
// if my data doesnt exist I will create one after that STOP listening
else {
// create circle
// do process 2
}
}
What you can do is use addListenerForSingleValueEvent
as it listens to the event only once
i.e. in your case
queryRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
if (datasnapshot.exists()) {
// code if data exists
} else {
// code if data does not exists
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Despite Shubham Arora's answer is the best solution for this case, I'm going to show you how to do exactly what you asked with these two solutions that are quite simple:
1. Global boolean
Create a global boolean and change it once your condition is met:
query.addListenerForSingleValueEvent(new ValueEventListener() {
boolean processDone = false;
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists() && !processDone) {
// do process 1
} else {
// do process 2
processDone = true;
}
}
#Override public void onCancelled(DatabaseError databaseError) {}
});
2. Remove listener
Remove your listener once your condition is met:
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
// do process 1
} else {
// do process 2
query.removeEventListener(this);
}
}
#Override public void onCancelled(DatabaseError databaseError) {}
});
Both solutions did work fine for me when I was using ChildEventListener and Shubham Arora's answer couldn't help.