Как непрерывно читать изменение значения в Firebase (Android)? - PullRequest
0 голосов
/ 08 сентября 2018

Я использую Firebase для мультиплеера. Все отлично работает, за исключением того, что мне нужно, когда один игрок закрывает приложение (onStop(), onDestroy() и т. Д.), Игра заканчивается. У меня есть следующая firebase структура:

"PVP" : {
    "active" : {
      "1536394217496" : {
        "didGameEnd" : true,
        "gameMaster" : {
          "didPlayerAnswer" : false,
          "name" : "stelios",
          "playerAnswerCorrect" : false,
          "score" : 2
        },
        "gameSlave" : {
          "didPlayerAnswer" : false,
          "name" : "anna",
          "playerAnswerCorrect" : false,
          "score" : 4
        },

У меня есть метод onDestroy, onDestroy и т. Д., Чтобы изменить "didGameEnd", работающий нормально. Моя проблема в том, что мне нужно поймать изменение, чтобы запустить код финальной игры. Я много пробовал, но не могу справиться. Вот мой код для этого:

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) {

            }
        });
    }

Как я понимаю, valueListener ловит datachange, поэтому мне не нужно делать здесь что-то особенное. Я думаю, проблема в значении boolean. Я попробовал это как строку без удачи.

Заданное значение работает нормально, поэтому, я думаю, я указываю в нужное место

mGameFirebase.child("didGameEnd").setValue(true);

Принесите любую помощь, если я новичок в Firebase!

После многих попыток следующий код

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) {

            }
        });

работает, но срабатывает даже при значении ЛОЖЬ. Так что на самом деле это просто читать значение, а не делать то, что мне нужно.

следующий код

     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) {

                }
            });

постоянно генерирует исключение Nullpoint.

Ответы [ 3 ]

0 голосов
/ 08 сентября 2018

Чтобы установить значение для вашего свойства didGameEnd от false до true, вам необходимо использовать следующие строки кода в вашем методе onStop():

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);

Чтобы постоянно проверять, изменяется ли это значение, вы должны добавить прослушиватель на одну и ту же ссылку, например:

didGameEndRef.addValueEventListener(/* ... */);

А внутри метода onDataChange() получите значение, используя следующие строки кода:

if(dataSnapshot.exists()) {
    boolean isEnded = dataSnapshot.getValue(Boolean.class);
    if(isEnded) {
        //Your logic
    }
}
0 голосов
/ 11 сентября 2018

Для дальнейшего использования работает следующий код:

// 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();
                    }
                }

Большое спасибо за работу!

0 голосов
/ 08 сентября 2018

Я предполагаю, что ваш mGameFirebase выглядит примерно так:

DatabaseReference mGameFirebase = FirebaseDatabase.getInstance().getReference().child("PVP");

Если это так, вы можете использовать childEventListener для прослушивания изменений в didGameEnd дочернем элементе вашей базы данных. Код не имеет много изменений просто, простые дополнения:

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) {

            }
        });

Если ваш mGameFirebase указывает на ссылку active или дочерних элементов ниже основного узла, вы можете попробовать это, которое сработает только после окончания игры и изменения значения:

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) {

            }
        });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...