应用程序进入后台时,实时多人Google Play游戏服务点对点连接会断开

3
我正在使用“Google Play Games Services”构建实时多人游戏。我的问题是,当同伴连接到房间并玩游戏时,如果其中一个将其应用程序置于后台,则该同伴会从房间中断开连接,并且其他同伴会收到该同伴离开房间的回调,有没有办法防止这种情况发生。
为了测试目的,在任何生命周期方法中,片段都不会调用离开该房间的方法。
我已添加了代码片段以提供更好的理解。
@Override
    public void onStop() {
        super.onStop();
//        if (mRoomId!=null && !mRoomId.isEmpty()) {
//            Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, mRoomId);
//        }
//        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//        mPlaying = false;
    }

        @Override
            public void onActivityResult(int request, int response, Intent data) {
                if (request == RC_SELECT_PLAYERS) {
                    if (response != Activity.RESULT_OK) {
                        // user canceled
                        return;
                    }

                    // get the invitee list
                    Bundle extras = data.getExtras();
                    final ArrayList<String> invitees =
                            data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);

                    // get auto-match criteria
                    Bundle autoMatchCriteria = null;
                    int minAutoMatchPlayers =
                            data.getIntExtra(Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
                    int maxAutoMatchPlayers =
                            data.getIntExtra(Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);

                    if (minAutoMatchPlayers > 0) {
                        autoMatchCriteria = RoomConfig.createAutoMatchCriteria(
                                minAutoMatchPlayers, maxAutoMatchPlayers, 0);
                    } else {
                        autoMatchCriteria = null;
                    }

                    // create the room and specify a variant if appropriate
                    RoomConfig.Builder roomConfigBuilder = makeBasicRoomConfigBuilder();
                    roomConfigBuilder.addPlayersToInvite(invitees);
                    if (autoMatchCriteria != null) {
                        roomConfigBuilder.setAutoMatchCriteria(autoMatchCriteria);
                    }
                    RoomConfig roomConfig = roomConfigBuilder.build();
                    Games.RealTimeMultiplayer.create(((MainActivity) getActivity()).getGoogleApiClient(), roomConfig);

                    // prevent screen from sleeping during handshake
                    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                }

                if (request == RC_WAITING_ROOM) {
                    if (mWaitingRoomFinishedFromCode) return;

                    if (response == Activity.RESULT_OK) {
                        // (start game)
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                if (getContext()!=null) {
                                    Player[] players = getParticipantPlayers();
                                    if (players!=null && players.length>0) {
                                        startGame(players);
                                    }
                                }
                            }
                        }, 1000);
                    }
                    else if (response == Activity.RESULT_CANCELED) {
                        // Waiting room was dismissed with the back button. The meaning of this
                        // action is up to the game. You may choose to leave the room and cancel the
                        // match, or do something else like minimize the waiting room and
                        // continue to connect in the background.

                        // in this example, we take the simple approach and just leave the room:
                        Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, mRoomId);
                        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                    }
                    else if (response == GamesActivityResultCodes.RESULT_LEFT_ROOM) {
                        // player wants to leave the room.
                        Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, mRoomId);
                        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                    }
                }
            }

    private RoomUpdateListener roomUpdateListener = new RoomUpdateListener() {

            @Override
            public void onJoinedRoom(int statusCode, Room room) {
                if (getContext()!=null) {
                    roomCreatorId = room.getCreatorId();
                    mRoomId = room.getRoomId();
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
    //            setCurrentPlayerParticipantId();
                    if (statusCode != GamesStatusCodes.STATUS_OK) {
                        // let screen go to sleep
                        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

                        // show error message, return to main screen.
                        Toast.makeText(getContext(), "Error while joining room.", Toast.LENGTH_SHORT).show();
                        showRoomUi();
                    }

                    // get waiting room intent
                    Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(((MainActivity) getActivity()).getGoogleApiClient(), room, MIN_PLAYERS);
                    startActivityForResult(i, RC_WAITING_ROOM);
                }
            }

            @Override
            public void onRoomCreated(int statusCode, Room room) {
                if (getContext()!=null) {
                    roomCreatorId = room.getCreatorId();
                    mRoomId = room.getRoomId();
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
    //            setCurrentPlayerParticipantId();
                    if (statusCode != GamesStatusCodes.STATUS_OK) {
                        // let screen go to sleep
                        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

                        // show error message, return to main screen.
                        Toast.makeText(getContext(), "Error creating room.", Toast.LENGTH_SHORT).show();
                        showRoomUi();
                    }

                    // get waiting room intent
                    Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(((MainActivity) getActivity()).getGoogleApiClient(), room, MIN_PLAYERS);
                    startActivityForResult(i, RC_WAITING_ROOM);
                }
            }


            @Override
            public void onLeftRoom(int i, String s) {
                if (getContext()!=null) {
    // remove the flag that keeps the screen on
                    mRoomId = null;
                }
            }

            @Override
            public void onRoomConnected(int statusCode, Room room) {
                if (getContext()!=null) {
                    roomCreatorId = room.getCreatorId();
                    mRoomId = room.getRoomId();
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
    //            setCurrentPlayerParticipantId();
                    if (statusCode != GamesStatusCodes.STATUS_OK) {
                        // let screen go to sleep
                        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

                        // show error message, return to main screen.
                        Toast.makeText(getContext(), "Error connecting to room.", Toast.LENGTH_SHORT).show();
                        showRoomUi();
                    }
                }
            }

        };


        private RoomStatusUpdateListener roomStatusUpdateListener = new RoomStatusUpdateListener() {

            @Override
            public void onRoomConnecting(Room room) {
                if (getContext()!=null) {
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                }
            }

            @Override
            public void onRoomAutoMatching(Room room) {
                if (getContext()!=null) {
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                }
            }

            @Override
            public void onPeerInvitedToRoom(Room room, List<String> list) {
                if (getContext()!=null) {
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                }
            }

            @Override
            public void onPeerJoined(Room room, List<String> list) {
                if (getContext()!=null) {
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                }
            }

            @Override
            public void onConnectedToRoom(Room room) {
                if (getContext()!=null) {
                    mMyId = room.getParticipantId(Games.Players.getCurrentPlayerId(((MainActivity) getActivity()).getGoogleApiClient()));
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                }
            }

            @Override
            public void onDisconnectedFromRoom(Room room) {

                if (getContext()!=null) {
    // leave the room
                    Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, room.getRoomId());

                    // clear the flag that keeps the screen on
                    getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

                    // show error message and return to main screen
                    Toast.makeText(getContext(), "Network error.", Toast.LENGTH_SHORT).show();

                    showRoomUi();
                }

            }

            @Override
            public void onP2PConnected(String s) {
            }

            @Override
            public void onP2PDisconnected(String s) {
            }

            @Override
            public void onPeersConnected(Room room, List<String> peers) {
                if (getContext()!=null) {
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                    if (mPlaying) {
                        // add new player to an ongoing game
                    } else if (shouldStartGame(room)) {
                        // start game!
                    }
                }
            }

            @Override
            public void onPeersDisconnected(Room room, List<String> peers) {
                if (getContext()!=null) {
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                    if (mPlaying) {
                        // do game-specific handling of this -- remove player's avatar
                        // from the screen, etc. If not enough players are left for
                        // the game to go on, end the game and leave the room.
                    }
                    else if (shouldCancelGame(room)) {
                        // cancel the game
                        Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, room.getRoomId());
                        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                        showRoomUi();
                    }
                }
            }

            @Override
            public void onPeerLeft(Room room, List<String> peers) {
                if (getContext()!=null) {
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                    // peer left -- see if game should be canceled
                    if (!mPlaying && shouldCancelGame(room)) {
                        Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, room.getRoomId());
                        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                        showRoomUi();
                    }
                }
            }

            @Override
            public void onPeerDeclined(Room room, List<String> peers) {
                if (getContext()!=null) {
                    mParticipants.clear();
                    mParticipants.addAll(room.getParticipants());
                    // peer declined invitation -- see if game should be canceled
                    if (!mPlaying && shouldCancelGame(room)) {
                        Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, room.getRoomId());
                        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                        showRoomUi();
                    }
                }
            }

        };

        private RealTimeMessageReceivedListener realTimeMessageReceivedListener = new RealTimeMessageReceivedListener() {
            @Override
            public void onRealTimeMessageReceived(RealTimeMessage realTimeMessage) {
                if (getContext()!=null) {
                    if (realTimeMessage.isReliable()) {
                        handleReliableMessages(realTimeMessage.getMessageData());
                    }
                }
            }
        };

非常感谢您的帮助。

以下是需要翻译的it技术相关内容:

1个回答

1
据我所知,这只是API设计的方式,并且按照意图工作。
文档中所述,当您的游戏进入后台时,应将活动房间离开。
有关更多见解(来自Bruno Oliveira),您可能希望查看以下相关SO帖子: 虽然,您也可以尝试此建议的解决方案。尝试编辑BaseGameActivity.onStop()并删除gamehelper.onStop()。通过这种方式,gamesclient仅在onDestroy中停止。这可能是一个不错的选择,但我实际上还没有尝试过。

将 gameHelper.onStop 移动到 onDestroy 对我有用。 - Sulabh Deep Puri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接