I have very simple database
TokenAdmin:
---xccsaccxvkkgmcdds :
---token: "cxcxzcfsdfdsfdsfs"
---uid: "xccsaccxvkkgmcdds"
---hjhbnghtfgdgdgdffg :
---token: "vhghtytyryyr"
---uid: "hjhbnghtfgdgdgdffg"
Now in my code I want to check and execute some code only if it find uid equal to "hjhbnghtfgdgdgdffg"
Here is my code :
mDatabase.child("TokenAdmin").orderByChild("uid").equalTo(mycurrUser.getUID()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//say here toast "A"
} else {
//toast "B"
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// ...
}
});
Now I run the code with mycurrUser.getUID() value set to "xxx" which I don't have listed in the database. I expected the code output was toast B, but instead I always get toast A, which in my understanding, it has found the value in the db. How to fix this, where did I do wrong ?
You need to use something like this:
mDatabase.child("TokenAdmin").orderByChild("uid").equalTo(mycurrUser.getUID()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
//Toast A
} else {
//Toast B
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
Hope it helps.
I'm confused why you're using a query to load the user. You seem to store the token under they UID key already, so this would work:
mDatabase.child("TokenAdmin").child(mycurrUser.getUID()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
... user exists
} else {
... user node does not exist
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
Related
I am creating an android app using firebase. My firebase database structure is as follow-
Users:{
uid:{
name:Bruno,
age: 22,
email: bruno#gmail.com,
address:...
}
},
Level_info:{
uid:{
score:70,
level:5
}
}
Before Rxjava, I retrieve all users like this-
userRef.addValueEventListener(new ValueEventListerner(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(Datasnapshot snapshot:dataSnapshot.getChildren())
{
User user = snapshot.getValue(User.class);
userList.add(user);
//to get score and levels
/*I can't add nested value event listener directly because of Asynchronous behavior */
userId.add(user.getId());
}
getLevels(userId);
}
#Override
public void onCancelled(DatabaseError error) {
//handle errors
}
});
void getLevels(final ArrayList<String> userid){
levelRef.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(String id:userid)
{
Level level = dataSnapshot.child(id).getValue(Level.class);
levelList.add(level);
}
/** Attch both "userList" and "levelList" to RecyclerView */
}
#Override
public void onCancelled(DatabaseError error) {
//handle errors
}
});
}
It goes fine.But if there are many nested Listeners, It will hard to read.So I tried to change to RxJava and RxAndroid. Like this-
public Observable<ArrayList<User>> userOb(){
return Observable.create(new
ObservableOnSubscribe<ArrayList<User>>() {
#Override
public void subscribe(final
ObservableEmitter<ArrayList<User>> emitter)
throws Exception {
FirebaseDatabase.getInstance().getReference("Users")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
ArrayList<UserModel> listUsers;
for(DataSnapshot snapshot: dataSnapshot.getChildren()){
User user = snapshot.getValue(User.class);
listUsers= new ArrayList<>();
listUsers.add(user);
emitter.onNext(listUsers);
}
emitter.onComplete();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
}
Here I don't know how to zip with LevelObservable because levelObservable need UserId from UserObservable to get data from Levels/(uid)/"level_info" .May be this is stupid question but I am new to RxJava. I want to get Corresponding userId from UserObservable to LevelObservable. So how can I do that?
Sorry for my bad English Writing skill.
Edit: Is there some ways to implement like this (because may be I miss some easy ways to implement).
I have issues on nested queries I'm trying to do using firebase, seems like the first query (activity1) doesn't wait until the second (activity2) and third query (activity3) finished running, this might return NULL value from the first query. Please look at my sample for more understanding, I've been stuck here for days trying all kind of method but it just wont work. :(
Query query_1= reference.child("Users").child("Room")
.child("Profile");
query_1.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//ACTIVITY 1
Query query_2 = reference.child("Users").child(Room)
.child("Receiver").child("id");
query_2.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//ACTIVITY 2
Query query_3 = reference.child("chatrooms").child("Room")
.child("Creator").child("id");
query_3.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//ACTIVITY 3
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
private FirebaseAuth firebaseAuth=FirebaseAuth.getInstance();;
private FirebaseUser firebaseUser=firebaseAuth.getCurrentUser();
/******************************After declaration**************************************/
userIDDatabaseReference=FirebaseDatabase.getInstance().getReference("login");
userIDDatabaseReference.child(firebaseUser.getUid()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.w("Show out:", "In Firebase ValueEventListener");
LoginClass tempClass=dataSnapshot.getValue(LoginClass.class);
loginID=tempClass.getLoginID();
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("Database Error: "+databaseError.getDetails());
}
});
above is my coding, I wanna retrieve loginID but my event listener does not fire as the log.w did't not print any log in my logcat, I think my function does not trigger the onDataChange() because every time it will return null for the loginID. Can someone tell me what am I missing?? I referred to all documentation related, I really don't figure out what is the problem over here.
thank you~~
Use a single value event listener to get the data one time. Use this code:
userIDDatabaseReference.child(firebaseUser.getUid()).addSingleValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.w("Show out:", "In Firebase ValueEventListener");
LoginClass tempClass=dataSnapshot.getValue(LoginClass.class);
loginID=tempClass.getLoginID();
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("Database Error: "+databaseError.getDetails());
}
});
I am having some touble with the following code snipped:
mCevap.child(post_key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
size = (int) dataSnapshot.getChildrenCount();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
viewHolder.setCount(size);
The size returns null but I don't understand why. I want to pass count values to recyclerview.
The data is loaded from Firebase asynchronously. This means that the order in which your code is execute is not what you're likely expecting. You can most easily see this by adding a few log statements to the code:
System.out.println("Before addListenerForSingleValueEvent");
mCevap.child(post_key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("In onDataChange");
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
System.out.println("After addListenerForSingleValueEvent");
The output of this is:
Before addListenerForSingleValueEvent
After addListenerForSingleValueEvent
In onDataChange
This is probably not what you expected! The data is loaded from Firebase asynchronously. And instead of waiting for it to return (which would cause an "Application Not Responding" dialog), the method continues. Then when the data is available, your onDataChange is invoked.
To make the program work, you need to move the code that needs the data into the onDataChange method:
mCevap.child(post_key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("size ="+dataSnapshot.getChildrenCount());
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
I wrote this code to get the values of a user who typed his username and i want to check his password :
MyDatabase.child("USERS").orderByChild("username").equalTo(Username.getText().toString())
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child :dataSnapshot.getChildren()){
Log.i("Password",child.getValue().toString());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
now i want to access the password field and check if the user entered the correct password or not .
There are 2 ways to achieve that. The first one is not to let the user leave an empty EditText when creating the account. And second is to verify if the dataSnapshot.exists(). Hope it helps!
This will work:
MyDatabase.child("USERS")
.orderByChild("username").equalTo(Username.getText().toString())
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child :dataSnapshot.getChildren()){
Log.i("Password",child.child("password").getValue().toString());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
The changes:
child.child("password").getValue()
don't ignore onCancelled()