Firebase query logic not working in android - java

I want to make a query that checks whether a certain name (President or Secretary) exists inside a database.
The structure of the database is as follows.
I have this code, but its not working. Is there something I'm doing wrong?
mDatabase = FirebaseDatabase.getInstance().getReference();
Query presidentquery = mDatabase.child("validate").child(uid).equalTo("President");
presidentquery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Candidate p = dataSnapshot1.getValue(Candidate.class);
president.setEnabled(false);
president.setText("Voted Already");
}
}
else{
president.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Home.this, AllCandidates.class));
finish();
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

It seems you know the exact node you want to load, in which case you don't need an equalTo. Instead you can look up the node with:
Query presidentquery = mDatabase.child("validate").child(uid).child("President");
The rest of your code can stay the same.

Related

How to retrieve push() valued data from Firebase to android

I am going to make a simple app and I am completely new to Android development. I want to develop an edit button to save my data in the Realtime Database. This is my code:
holder.edite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final DialogPlus dialogPlus=DialogPlus.newDialog(holder.title.getContext())
.setContentHolder(new ViewHolder(R.layout.dialogcontent))
.setExpanded(true,2100)
.create();
View myView=dialogPlus.getHolderView();
EditText title=myView.findViewById(R.id.hTitle);
EditText description=myView.findViewById(R.id.hDescription);
Button submit=myView.findViewById(R.id.usubmit);
title.setText(myItems.getName());
description.setText(myItems.getAddHomeworkDescription());
dialogPlus.show();
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Map<String,Object> map=new HashMap<>();
map.put("name",title.getText().toString());
map.put("addHomeworkDescription",description.getText().toString());
DatabaseReference myRef = getInstance().getReference().child("Homework");
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
// String key = myRef.push().getKey();
myRef.child(uid).child()
.updateChildren(map);
dialogPlus.dismiss();
}
});
}
});
This is how my firebase database looks like
What I want to add into .child() to get highlighted(In the image) Unique id direction. But this unique ID is not always same. It change everythime when user create new one.
You will either have to know the push key (-NN...) value of the node you want to update already, determine it with a query, or loop over all child nodes and update them all.
Update a specific child with a known push key
myRef.child(uid).child("-NNsQO7O9lh0ShefShV")
.updateChildren(map);
Update children matching a specific query
Say that you know you want to update the node with name "test12", you can use a query for that:
myRef.child(uid).orderByChild("name").equalToValue("test12").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot nodeSnapshot: dataSnapshot.getChildren()) {
nodeSnapshot.getRef().updateChildren(map);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})
Update all children
This is a simpler version of the above, by removing the query condition:
myRef.child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot nodeSnapshot: dataSnapshot.getChildren()) {
nodeSnapshot.getRef().updateChildren(map);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})

Firebase not retrieve last data when data changes and not execute conditions inside addValueEventListener in the right way

I'm trying to execute some code in my addValueEventListener based on conditions of values in database, but when data changes, listener execute conditions based on old data, and at the second try listener perform data which I want to use. however data change listener perform listenr(-1) data. To be more clear, if "disable" or "stop" child exist I don't want to execute the code, but after data are updated and these children not existing, conditions when I call AddMessage method not executing again, but it execute method when I call for the second time, it perform correctly till next update of the data where it start again same issue.
sendMessage.setOnClickListener(new View.OnClickListener() {#Override
public void onClick(View v) {
AddMessage();
}
});
private void AddMessage() {
nListener = RootRef.child("List Ref").child(messageReceiverID).child(messageSenderID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
if (!dataSnapshot.hasChild("disable") && !dataSnapshot.hasChild("stop")) {
HashMap <String,String> chatMessageMap = new HashMap <>();
chatMessageMap.put("from", messageSenderID);
chatMessageMap.put("type", "check");
chatMessageMap.put("content", messageText);
MessagesRef.child(messageReceiverID).push().setValue(chatMessageMap);
RootRef.child("List Ref").child(messageReceiverID).child(messageSenderID).removeEventListener(nListener);
} else {
RootRef.child("List Ref").child(messageReceiverID).child(messageSenderID).removeEventListener(nListener);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
sendMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String stoppedUser;
myDbref = FirebaseDatabase.getInstance().getReference().child("List Ref").child(<UID_OF_RECEIVER_OF_MESSAGE>);
myDbref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
try {
stoppedUser = dataSnapshot.child(<UID_OF_SENDER>).child("stop").getValue().toString();
//Now use if-else statement
if(<UID_OF_RECEIVER> == stoppedUser){
Toast.makeText(getApplicationContext(), "You are blocked.", Toast.LENGTH_LONG).show();
} else {
AddMessage();
}
}catch (Throwable e){
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Though you can get <UID_OF_SENDER> by using FirebaseUser currentUserUID = FirebaseAuth.getInstance().getCurrentUser();
Make sure you put the value of <UID_OF_RECEIVER> correctly and also correct the database path if needed.

How to copy data from one table to another table in Firebase?

I have two tables - cartOrders and placedOrders. cartOrders is used to add products to cart, and placedOrders is activated when the user presses "Place Order" button.
I need to copy data from cartOrders to placedOrders when the user clicks the "Place Order" button, but I'm not able to do so.
cartDatabase = FirebaseDatabase.getInstance().getReference("cartOrders");
cartQuery = cartDatabase.child(orderID).orderByChild("productQuantity").startAt(1);
placedOrdersDatabase = FirebaseDatabase.getInstance().getReference("placedOrders");
placedOrderQuery = placedOrdersDatabase.child("orderID");
placeOrderButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
cartDatabase.child(orderID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//Logic to add data to data to placedOrders.
String name = dataSnapshot.child("productName").getValue(String.class);
System.out.println("ProductName: " + name);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Intent intent = new Intent(getApplicationContext(), OrderPlacedActivity.class);
intent.putExtra("ORDER_ID", orderID);
startActivity(intent);
}
});
In the code, I was checking if the code is picking up the data from the database, but it wasn't. The output is null. Both the tables have the same structure.
Any help will be appreciated.
Thanks!
My cartOrders table structure:
cartOrders:
----------OrderID:
-----------------ProductID:
---------------------------ProductID:
---------------------------ProductName:
---------------------------ProductPrice:
---------------------------ProductQty:
#Alex Mamo answered this question on a different question.
private void copyRecord(Query fromPath, final DatabaseReference toPath) {
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
toPath.setValue(dataSnapshot.getValue()).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isComplete()) {
System.out.println("Complete");
} else {
System.out.println("Failed");
}
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
fromPath.addListenerForSingleValueEvent(valueEventListener);
}
The code works fine.
Link:Moving or copying data from one node to another in firebase database

How to read continiusly a value change in Firebase (Android)?

I use Firebase for multiplayer. Everything works great except that I need when one player closes app (onStop(), onDestroy() etc) the game ends. I have the following firebase structure:
"PVP" : {
"active" : {
"1536394217496" : {
"didGameEnd" : true,
"gameMaster" : {
"didPlayerAnswer" : false,
"name" : "stelios",
"playerAnswerCorrect" : false,
"score" : 2
},
"gameSlave" : {
"didPlayerAnswer" : false,
"name" : "anna",
"playerAnswerCorrect" : false,
"score" : 4
},
I have in onDestroy, onDestroy etc method to change the "didGameEnd" working fine. My problem is I need to catch the change to run the endgame code. I tried a lot but i cant manage it. Here is my code for this:
mGameFirebase = FirebaseDatabase.getInstance()
.getReferenceFromUrl(Constants.FIREBASE_BASE_URL + Constants.FIREBASE_PVP + Constants.FIREBASE_GAME_ACTIVE_PATH + mGameWaitModel.getId());
public void ifGameEnds() {
mGameFirebase.child("didGameEnd").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Boolean isEnded = (Boolean) dataSnapshot.getValue();
if (isEnded == true) {
Intent intent = new Intent(getApplicationContext(), PvPWinningActivity.class);
Bundle dataSend = new Bundle();
dataSend.putString("Winning Text", winning_text);
dataSend.putInt("Your Score", your_Score);
dataSend.putInt("Opponent Score", opponent_score);
intent.putExtras(dataSend);
startActivity(intent);
finish();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
As i can understand the valueListener catches the datachange so i dont need to do something special here. I guess the problem is with the boolean value. I tried it as string with no luck.
Set value works fine so i guess i m pointing in the right place
mGameFirebase.child("didGameEnd").setValue(true);
Appriciate any help for what is wrong as i m new at Firebase!
After many tries the following code
mGameFirebase.orderByChild("didGameEnd").equalTo(true).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// this will be triggered only when the value is true, so you can add the thing that you want to make happen, here only
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
works BUT it triggers even of the value is FALSE. So actually its just read the value, not doing what i need.
The following code
mGameEnd =FirebaseDatabase.getInstance()
.getReferenceFromUrl(Constants.FIREBASE_BASE_URL + Constants.FIREBASE_TEST_PATH + Constants.FIREBASE_GAME_ACTIVE_PATH + mGameWaitModel.getId());
mGameEnd.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
boolean isEnded = dataSnapshot.getValue(Boolean.class);
if(isEnded) {
//Your logic
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
throws Nullpoint exception all the time.
To set the value for your didGameEnd property from false to true, you need to use the following lines of code in your onStop() method:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference didGameEndRef = rootRef
.child("PVP")
.child("active")
.child(uid)
.child("didGameEnd");
didGameEndRef.setValue(true);
To constantly check if this value is changed, you should add the listener on the same reference like this:
didGameEndRef.addValueEventListener(/* ... */);
And inside the onDataChange() method, get the value using these lines of code:
if(dataSnapshot.exists()) {
boolean isEnded = dataSnapshot.getValue(Boolean.class);
if(isEnded) {
//Your logic
}
}
I am guessing that your mGameFirebase looks something like this:
DatabaseReference mGameFirebase = FirebaseDatabase.getInstance().getReference().child("PVP");
If it does, you can use childEventListener to listen to the changes in didGameEnd child of your database. The code does not have many changes just, simple additions :
mGameFirebase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Boolean isEnded = (Boolean) dataSnapshot.child("didGameEnd").getValue();
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
If your mGameFirebase points to the reference of the active or children below the main node, you can try this, which will only be triggered when the game ends and the value changes:
mGameFirebase.orderByChild("didGameEnd").equalTo(true).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// this will be triggered only when the value is true, so you can add the thing that you want to make happen, here only
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
For future reference the following code works:
// initialize the game state listener
mGameEnd = FirebaseDatabase.getInstance()
.getReferenceFromUrl(Constants.FIREBASE_BASE_URL + Constants.FIREBASE_TEST_PATH + Constants.FIREBASE_GAME_ACTIVE_PATH + mGameWaitModel.getId());
mGameEnd.child("didGameEnd").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
boolean isEnded = (Boolean) dataSnapshot.getValue();
if(isEnded){
if (isGameMaster()) {
your_Score = 0;
opponent_score = mGameModel.getGameSlave().getScore();
winning_text = "You Lost!";
}
if (!isGameMaster()) {
your_Score = 0;
opponent_score = mGameModel.getGameMaster().getScore();
winning_text = "You lost";
}
Intent intent = new Intent(getApplicationContext(), PvPWinningActivity.class);
Bundle dataSend = new Bundle();
dataSend.putString("Winning Text", winning_text);
dataSend.putInt("Your Score", your_Score);
dataSend.putInt("Opponent Score", opponent_score);
intent.putExtras(dataSend);
startActivity(intent);
finish();
Toast.makeText(getApplicationContext(), "Game Over", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(getApplicationContext(), "Keep Playing", Toast.LENGTH_LONG).show();
}
}
Thanks a lot for the efford!

how to make sure Query is not empty

i have an application with many types of users like normalUser,PremiumUser
and in order to define that i use their unique UID in firebasedatabase to each one in their category premium or normal
this is my database firebase shape
--users
-----normal
-----premium
so if user choose normal account he will be assigned to normal only
for me this is how to grab his data later when he log in is as follows
if (auth.getCurrentUser() != null) {
finish();
Query q = FirebaseDatabase.getInstance().getReference().child("users").child("normal").equalTo(auth.getCurrentUser().getUid());
Query q2 = FirebaseDatabase.getInstance().getReference().child("users").child("premium").equalTo(auth.getCurrentUser().getUid());
if (q != null) {
q.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
startActivity(new Intent(Login.this, Normal.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
} else {
q2.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
startActivity(new Intent(Login.this, Premium.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
but looks like the code enter both activities altough for sure this account exists in one of categories only(normal or premium)
i tried using
if (dataSnapshot.getChildrenCount()>0) //none of both activities is entered
if (dataSnapshot != null)//both Activites still entered
if(dataSnapshot.getValue(Premium.class)!=null)//vvvv
if(dataSnapshot.getValue(Normal.class)!=null)//but still none entered
i also tried
Query q = FirebaseDatabase.getInstance().getReference().child("users").child("normal").equalTo(auth.getCurrentUser().getUid());
final Query q2 = FirebaseDatabase.getInstance().getReference().child("users").child("premium").equalTo(auth.getCurrentUser().getUid());
q.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
startActivity(new Intent(Login.this, Normal.class));
}
else {
q2.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
startActivity(new Intent(Login.this, Premium.class));
}
but none of them was entered too
how can i fix that
thanks
Your query will never be null, because you created it just before that. There is no way to know how many results a query has without attaching a listener.
So the closest you can get with your current data structure is to nest the queries:
Query q = FirebaseDatabase.getInstance().getReference().child("users").child("normal").equalTo(auth.getCurrentUser().getUid());
Query q2 = FirebaseDatabase.getInstance().getReference().child("users").child("premium").equalTo(auth.getCurrentUser().getUid());
q.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
startActivity(new Intent(Login.this, Normal.class));
}
else {
q2.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
startActivity(new Intent(Login.this, Premium.class));
}
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
}
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
A more direct way to make this work is to change your data structure so that is also contains the payment status for each user. So also store:
user_payment_status
uid1: "normal"
uid2: "premium"
Then you can simply look up the status for the current user with a single value listener. You'll keep your current list around, since you likely also want to show a list of all premium users somewhere in the app.
Duplicating data in this way is quite common in NoSQL databases.
i fixed it by adding to each user a uid then changed
Query q = FirebaseDatabase.getInstance().getReference().child("users").child("normal").equalTo(auth.getCurrentUser().getUid());
Query q2 = FirebaseDatabase.getInstance().getReference().child("users").child("premium").equalTo(auth.getCurrentUser().getUid());
to the following
Query q = FirebaseDatabase.getInstance().getReference().child("users").child("normal").orderByChild("uid").equalTo(auth.getCurrentUser().getUid());
Query q2 = FirebaseDatabase.getInstance().getReference().child("users").child("premium").orderByChild("uid").equalTo(auth.getCurrentUser().getUid());
i still dont know why the first way is wrong

Categories

Resources