Not sure why, but with the code I have, I cannot seem to get the value of 'isOnline':
dolRef = DatabaseReference dolRef = FirebaseDatabase.getInstance().getReference("DriversOnline");
dolRef = dolRef.child("iosDriver");
dolRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String driverid = ds.getKey();
// get value of 'isOnline'
dolRef = dolRef.child(driverid);
Log.e(TAG, "dolRef: " + dolRef);
dolRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot dss : dataSnapshot.getChildren()) {
String online = dss.child("isOnline").getValue(String.class);
Log.e(TAG, "Online: " + online);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Below is a part of my firebase db:
"DriversOnline" : {
"iosDriver" : {
"BruEGfToc8axIWJk1o01fxcwd8I2" : { // driverId
"isOnline" : "true",
"latitude" : 45.276,
"longitude" : -66.064
}
}
}
Any idea why I can't get the value of 'isOnline' other than null ?
I think you're nesting your listeners one level deeper than needed.
DatabaseReference iosRef = FirebaseDatabase.getInstance().getReference("DriversOnline/iosDriver");
iosRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot driverSnapshot: dataSnapshot.getChildren()) {
String driverid = driverSnapshot.getKey();
DataSnapshot isOnlineSnapshot = driverSnapshot.child("isOnline");
System.out.println(isOnlineSnapshot.getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
Some things to note:
Reassigning one generically named dolRef variable 4 times in a block of code like this is a code-smell. It makes it much harder to follow what's going on, and to check if the variable points to the right location. Give each of them a name that clearly indicates what they point to, as I've done above.
There is no need to attach a second listener, as the value of isOnline is right in the driverSnapshot. You can just request the child snapshot with the right name, and then the value from that.
Don't ignore error, as that hides potential problems. At the very least throw them, as I've done above.
driverid = FirebaseDatabase.getInstance().getReference("driver");//If there is another driver table, the path must be two layers.
driverid.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Driver driver = dataSnapshot.getValue(Driver.class);//class model
dolRef = FirebaseDatabase.getInstance().getReference("DriversOnline/iosDriver").child(driver.getDriverID);
dolRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DriversOnline driversOnline= dataSnapshot.getValue(DriversOnline .class);//class model
log.d("driverid","isOnline :"+driversOnline.getisOnline)
//display -> isOnline : true
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Related
Here is my Firebase Realtime Database structure:
I want to retrieve each and every image in a child(images1,images2,images3,images4 are the child names)
private void loadmybanners1() {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("BannerImages");
ref.orderByChild("images2").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds : snapshot.getChildren()) {
final String myImg1 = "" + ds.child("image").getValue();
try{
Picasso.get().load(myImg1).networkPolicy(NetworkPolicy.OFFLINE).into(ban2Iv, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
Picasso.get().load(myImg1).into(ban2Iv);
}
});
} catch (Exception e) {
ban2Iv.setImageResource(R.drawable.ic_image);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
I have used this code to retrieve the image2. But from that, I can only retrieve the images1 child data. What are the modifications to do?
I want to retrieve each and every image in a child
To get each and every child within your BannerImages node, there is no need to use a query, you can simply use a DatabaseReference, as in the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference bannerImagesRef = rootRef.child("BannerImages");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String myImg1 = dataSnapshot.child("images1").child("image").getValue(String.class);
Picasso.get().load(myImg1)
String myImg2 = dataSnapshot.child("images2").child("image").getValue(String.class);
Picasso.get().load(myImg2)
//And so on for the other images3, images4, and images5 children
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore errors!
}
};
bannerImagesRef.addListenerForSingleValueEvent(valueEventListener);
Add this dependency
implementation 'com.github.bumptech.glide:glide:4.10.0'
After getting Url from Firebase.Just Use below line
Glide.with(context).load(Firbase Url).into(imageView);
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!
{
"History" : {
"-LIRZ4Nf2HyTTYtZEeOA" : {
"destination" : "101 Main Street, Your Town, Your Country",
"driver" : "vP9r4F2yDWRRuvKjRiQvMEXVuoK2",
"payment response" : "approved",
"rating" : 0,
"ridePrice" : 3.63,
"rider" : "C0RjB5NPZcTvWz9XiUAhpTDOK0C2",
"status" : "accepted",
"timestamp" : 1532709012
}
}
The above is the History node in my Firebase database.
My ultimate goal is to send an alert dialog once the payment response = "approved" but, in this case, when there is more than one key in the History node, the alerts run on top of each other.
What can I do so this does not happen?
The code I am using to get the key for each History entry is:
private void getPaymentResponse() {
final DatabaseReference paymentConfirmed = FirebaseDatabase.getInstance().getReference("History");
paymentConfirmed.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
ryydeKey = ds.getKey(); **<-- gets the key**
DatabaseReference response = FirebaseDatabase.getInstance().getReference("History")
.child(ryydeKey);
response.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
if (child.getKey().equals("payment response")) {
String response = String.valueOf(child.getValue().toString());
if (response.equals("approved")) {
proceedToPickupDialog();
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I am assuming that the code:
for(DataSnapshot ds : dataSnapshot.getChildren()) {
ryydeKey = ds.getKey();
is getting all the keys, but all I want is the present key.
Edit
I am putting in this code and nothing is printing up. Tried logs and toasts.
DatabaseReference payRef = FirebaseDatabase.getInstance().getReference();
Query query = payRef.child("History").orderByChild("driver").equalTo(driverId).limitToLast(1);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String response = ds.child("payment response").getValue(String.class);
Log.e(TAG, "response = " + response);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
query.addListenerForSingleValueEvent(valueEventListener);
When you are using getChildren() method, it means that you are looping through the entire DataSnapshot object. If the DataSnapshot contains more then one child, then the alerts will run on top of each other. If you want to check only for a particular child, you need to change the code a little bit.
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference idRef = rootRef.child("History").child("-LIRZ4Nf2HyTTYtZEeOA");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String response = dataSnapshot.child("payment response").getValue(String.class);
if(response.equalTo("approved")) {
Log.d("TAG", "Payment approved!");
} else {
Log.d("TAG", "Payment not approved!");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
idRef.addListenerForSingleValueEvent(valueEventListener);
Using this code, you get only the response form a single child. To actually get this work done, first you need to store this value -LIRZ4Nf2HyTTYtZEeOA in a variable in order to be able to use in your reference.
Edit: This another approach using a query"
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("History").orderByChild("driver").equalsTo(driverId).limitToLast(1);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String response = dataSnapshot.child("payment response").getValue(String.class);
if(response.equalTo("approved")) {
Log.d("TAG", "Payment approved!");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
query.addListenerForSingleValueEvent(valueEventListener);
I have been searching for a few days, but couldn't find the solution for my problem.
I would like to get the key of the value that is selected in the spinner. The spinner contains an arraylist of the names in the database.
Button Testing = (Button)findViewById(R.id.Testing);
Testing.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
p1ID = playerOneSpinner.getSelectedItem().toString();
DatabaseReference db = (DatabaseReference)
FirebaseDatabase.getInstance().getReference().child("id");
db.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot val : dataSnapshot.getChildren()){
data = val.toString();
Log.e("HALLO", data);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Log.e("HALLO", p1ID + " <-- this is the spinner");
}
});
This is how my database lookslike
LadderCompetition
- id
-1
Jeroen
-2
Franky
-3
Jesper
-4
Rob
output of logcat
DatabaseReference db = (DatabaseReference)
FirebaseDatabase.getInstance().getReference().child("id");
db.orderByValue().equalTo(p1ID).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot val : dataSnapshot.getChildren()){
data = val.toString();
Log.e("HALLO", data);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here is my firebase data structure . The child "Tags" is a child of root.
final Query searchquery = mDatabase.child("Tags").orderByKey().limitToFirst(10).startAt(s.toString().toLowerCase()).endAt(s.toString().toLowerCase() + "\uf8ff");
searchquery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
try {
String u = dataSnapshot.child("article_name").getValue(String.class);
Toast.makeText(MainActivity.this,":/ : "+u.toString(),Toast.LENGTH_LONG).show();
}catch (Exception tg){
Toast.makeText(MainActivity.this,tg.toString(),Toast.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I want to get the value of child "article_name" . I used the code above . But it is returning null .
Please use this code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference tagsRef = rootRef.child("Tags");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String article_name = ds.child("article_name").getValue(String.class);
Log.d("TAG", tagsRef);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
tagsRef.addListenerForSingleValueEvent(eventListener);
The output will be:
Blood Circulation
Dummy Article
Also don't forget to use names for the keys that does not contain any spaces. So you need to change blood circulation in blood_circulation or bloodCirculation