Reputation: 141
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.
Upvotes: 2
Views: 818
Reputation: 141
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!
Upvotes: 0
Reputation: 138824
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
}
}
Upvotes: 2
Reputation: 2375
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) {
}
});
Upvotes: 1