Android Google Play Game Services多玩家设备定位的改变将用户踢出了游戏空间
我正在开发一个应用程序,它只有一个活动(扩展了BaseGameActivity),并在多个片段之间切换(很像谷歌的示例代码状态) 我现在正在测试一个多人游戏,在两个不同的设备上。两个用户都可以成功登录、互相发送消息等。但是,一旦一个用户旋转设备,他们就会被踢出房间 我认为这是有意义的,因为活动正在被破坏和重新创建。但我不明白的是我们需要做什么才能让用户旋转他们的设备,并保持游戏状态(登录、加入房间等)?Android Google Play Game Services多玩家设备定位的改变将用户踢出了游戏空间,android,multiplayer,device-orientation,google-play-games,Android,Multiplayer,Device Orientation,Google Play Games,我正在开发一个应用程序,它只有一个活动(扩展了BaseGameActivity),并在多个片段之间切换(很像谷歌的示例代码状态) 我现在正在测试一个多人游戏,在两个不同的设备上。两个用户都可以成功登录、互相发送消息等。但是,一旦一个用户旋转设备,他们就会被踢出房间 我认为这是有意义的,因为活动正在被破坏和重新创建。但我不明白的是我们需要做什么才能让用户旋转他们的设备,并保持游戏状态(登录、加入房间等)? 一个想法是:android:configChanged=“orientation | sc
- 一个想法是:android:configChanged=“orientation | screenSize”-但android不鼓励这样做(在大多数情况下有很好的理由)-但这是我们必须使用Google Play游戏服务才能在设备方向改变的情况下呆在房间里的方式吗
- 使用“OnRetainOnConfigurationInstance()”保存GameHelper实例,并在重新创建活动时再次使用它,怎么样
- 或者以某种方式在服务中实现游戏连接(登录、加入房间等)
还是我想得不对?!谢谢你的想法和帮助。如果可能的话,我们也非常感谢代码示例。这里有一个想法。但在此之前,我要做一点说明 Android资源管理器可以随时因内存或其决定的任何原因杀死Android应用程序。因此,为了保持一个“永远在线”的永久执事,我们使用服务 这里有一个服务是很好的,因为你的应用程序可以将它的状态传达给服务,服务反过来保存所有真实数据(已连接、连接到哪个服务器、服务器连接等),并且只需重新连接到服务 使用此服务将增加一个额外的好处,即可能会告诉您远程客户端已断开连接(如果该服务未绑定到应用程序,则用户def已断开连接),并有助于精细颗粒化连接,因为该服务在您的服务器和GUI客户端之间进行调解。出于所有意图和目的,服务是真正的玩游戏的客户机,它只是由gui客户机驱动,gui客户机告诉服务它应该尝试做什么。这样,用户看不到服务,并且始终保留其播放状态 但首先,我会尝试通过AndroidManifest使我的应用程序成为一个单实例,只使用应用程序的一个实例(singleTop)或始终使用相同的进程(sameProcess,但不确定这是否有帮助)
如果失败了,我会选择好的,不那么痛苦的路线,直到最后我看到服务是我要走的路。因此,也许有一个轻量级的解决方案可以解决您的问题,也许您只需要一个简单的deamon服务,就到此为止。我遇到了完全相同的问题,我目前正在解决这个问题 最初我只是使用
android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
在清单中,因为我的游戏和基于片段的游戏服务实现都不正确地支持方向更改。i、 我相信这些缺点是我自己的代码,而不是谷歌提供的东西
在我的例子中,用户被踢出游戏,因为当一个或另一个玩家“旋转”时,我没有正确地重新启动我的片段。然后我收到onLeftRoom回调,并选择在此时结束
我正借此机会改进和简化我自己基于片段的游戏服务实现,这是我的基本计划:
一种片段活性(ABS),包括:
- 一些简单的UI片段选项卡,用于“快速游戏”、“排行榜”等
- 一个“headless”(无UI)setRetainInstance(true)片段,它相当于我的“BaseGameActivity”示例,执行所有 调用GameHelper
- GameHelper-未更改提供的版本
感谢@Sheldon为我指出了关于“无头”片段的
setRetainInstance(true)
的正确方向。这就是我解决这个问题的方法,现在我想把我的代码粘贴到这里,希望能帮助其他人。但首先:
口头解释
如问题中所述,设备方向更改将破坏MainActivity extends BaseGameActivity
,并随之破坏您的游戏状态(即您与Google Play服务的连接)。但是,我们可以将所有GameHelper代码放入一个“headless”片段(一个没有UI的片段),并声明setRetainInstance(true)
。现在,当我们的MainActivity extends FragmentActivity
在方向改变时被销毁时,无头碎片会停止,甚至分离,但不会被销毁!(onDestroy()
public class GameHelperFragment extends Fragment implements GameHelperListener, OnInvitationReceivedListener, RoomUpdateListener, RoomStatusUpdateListener, RealTimeMessageReceivedListener {
protected MainActivity mActivity = null;
// The game helper object. This class is mainly a wrapper around this object.
protected GameHelper mHelper;
final static int MAX_NUM_PLAYERS = 4;
// Request codes for the UIs that we show with startActivityForResult:
final static int RC_SELECT_PLAYERS = 10000;
final static int RC_INVITATION_INBOX = 10001;
final static int RC_WAITING_ROOM = 10002;
// We expose these constants here because we don't want users of this class
// to have to know about GameHelper at all.
public static final int CLIENT_GAMES = GameHelper.CLIENT_GAMES;
public static final int CLIENT_APPSTATE = GameHelper.CLIENT_APPSTATE;
public static final int CLIENT_PLUS = GameHelper.CLIENT_PLUS;
public static final int CLIENT_ALL = GameHelper.CLIENT_ALL;
// Requested clients. By default, that's just the games client.
protected int mRequestedClients = CLIENT_GAMES;
protected String mSigningInMessage = "Signing in with Google";
protected String mSigningOutMessage = "Signing out";
// Custom Members
String mMyId = "";
String mRoomId = "";
ArrayList<Participant> mParticipants = null;
int mCurrentlyPlayingIdx = 0; // idx into mParticipants
boolean mIsMultiplayer = false;
boolean mWaitRoomDismissedFromCode = false;
public interface GameHelperFragmentListener {
void onSignInFailed();
void onSignInSucceeded();
void onInvitationReceived(Invitation invitation);
void showMainMenu();
void showWaitScreen();
void startGame();
void participantLeftAtIdx(int idx);
void handleRealTimeMessage(RealTimeMessage rtm);
}
GameHelperFragmentListener mListener;
public GameHelperFragment() {
super();
Log.d("mab", "GHFrag.Constructor()");
}
/**
* Sets the requested clients. The preferred way to set the requested clients is
* via the constructor, but this method is available if for some reason your code
* cannot do this in the constructor. This must be called before onCreate in order to
* have any effect. If called after onCreate, this method is a no-op.
*
* @param requestedClients A combination of the flags CLIENT_GAMES, CLIENT_PLUS
* and CLIENT_APPSTATE, or CLIENT_ALL to request all available clients.
*/
protected void setRequestedClients(int requestedClients) {
mRequestedClients = requestedClients;
}
@Override
public void onAttach(Activity activity) {
Log.d("mab", this + ": onAttach(" + activity + ")");
super.onAttach(activity);
mActivity = (MainActivity) activity;
mListener = (GameHelperFragmentListener) activity;
}
@Override
public void onCreate(Bundle b) {
Log.d("mab", this + ": onCreate()");
super.onCreate(b);
setRetainInstance(true);
mHelper = new GameHelper(mActivity);
mHelper.setup(this, mRequestedClients); //'this' => GameHelperListener
mHelper.setSigningInMessage(mSigningInMessage);
mHelper.setSigningOutMessage(mSigningOutMessage);
mHelper.onStart(mActivity);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return null; // Headless Fragment
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.d("mab", this + ": onActivityCreated()");
super.onActivityCreated(savedInstanceState);
}
@Override
public void onDestroy() {
Log.d("mab", this + ": onDestroy()");
super.onDestroy();
mHelper.onStop();
}
@Override
public void onActivityResult(int requestCode, int responseCode, Intent data) {
Log.d("mab", this + ": onActivityResult(" + requestCode + ")");
super.onActivityResult(requestCode, responseCode, data);
mHelper.onActivityResult(requestCode, responseCode, data);
switch (requestCode) {
case RC_SELECT_PLAYERS:
// we got the result from the "select players" UI -- ready to create the room
handleSelectPlayersResult(responseCode, data);
break;
case RC_INVITATION_INBOX:
// we got the result from the "select invitation" UI (invitation inbox). We're
// ready to accept the selected invitation:
handleInvitationInboxResult(responseCode, data);
break;
case RC_WAITING_ROOM:
// ignore result if we dismissed the waiting room from code:
if (mWaitRoomDismissedFromCode) break;
// we got the result from the "waiting room" UI.
if (responseCode == Activity.RESULT_OK) {
} else if (responseCode == GamesActivityResultCodes.RESULT_LEFT_ROOM) {
// player actively indicated that they want to leave the room
leaveRoom();
} else if (responseCode == Activity.RESULT_CANCELED) {
leaveRoom();
}
break;
}
}
// Handle the result of the "Select players UI" we launched when the user clicked the
// "Invite friends" button. We react by creating a room with those players.
private void handleSelectPlayersResult(int responseCode, Intent data) {
if (responseCode != Activity.RESULT_OK) {
Log.w("mab", "*** select players UI cancelled, " + responseCode);
showMainMenu();
return;
}
Log.d("mab", "Select players UI succeeded.");
// get the invitee list
final ArrayList<String> invitees = data.getStringArrayListExtra(GamesClient.EXTRA_PLAYERS);
Log.d("mab", "Invitee count: " + invitees.size());
// get the automatch criteria
Bundle autoMatchCriteria = null;
int minAutoMatchPlayers = data.getIntExtra(GamesClient.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
int maxAutoMatchPlayers = data.getIntExtra(GamesClient.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
if (minAutoMatchPlayers > 0 || maxAutoMatchPlayers > 0) {
autoMatchCriteria = RoomConfig.createAutoMatchCriteria(
minAutoMatchPlayers, maxAutoMatchPlayers, 0);
Log.d("mab", "Automatch criteria: " + autoMatchCriteria);
}
// create the room
Log.d("mab", "Creating room...");
RoomConfig.Builder rtmConfigBuilder = RoomConfig.builder(this);
rtmConfigBuilder.addPlayersToInvite(invitees);
rtmConfigBuilder.setMessageReceivedListener(this);
rtmConfigBuilder.setRoomStatusUpdateListener(this);
if (autoMatchCriteria != null) {
rtmConfigBuilder.setAutoMatchCriteria(autoMatchCriteria);
}
showWaitScreen();
keepScreenOn();
getGamesClient().createRoom(rtmConfigBuilder.build());
Log.d("mab", "Room configured, waiting for it to be created...");
}
// Handle the result of the invitation inbox UI, where the player can pick an invitation
// to accept. We react by accepting the selected invitation, if any.
private void handleInvitationInboxResult(int response, Intent data) {
if (response != Activity.RESULT_OK) {
Log.d("mab", "*** invitation inbox UI cancelled, " + response);
showMainMenu();
return;
}
Log.d("mab", "Invitation inbox UI succeeded.");
Invitation inv = data.getExtras().getParcelable(GamesClient.EXTRA_INVITATION);
// accept invitation
acceptInviteToRoom(inv.getInvitationId());
}
protected GamesClient getGamesClient() {
return mHelper.getGamesClient();
}
protected AppStateClient getAppStateClient() {
return mHelper.getAppStateClient();
}
protected PlusClient getPlusClient() {
return mHelper.getPlusClient();
}
protected boolean isSignedIn() {
return mHelper.isSignedIn();
}
protected void beginUserInitiatedSignIn() {
mHelper.beginUserInitiatedSignIn();
}
protected void signOut() {
mHelper.signOut();
}
protected void showAlert(String title, String message) {
mHelper.showAlert(title, message);
}
protected void showAlert(String message) {
mHelper.showAlert(message);
}
protected void enableDebugLog(boolean enabled, String tag) {
mHelper.enableDebugLog(enabled, tag);
}
protected String getInvitationId() {
return mHelper.getInvitationId();
}
protected void reconnectClients(int whichClients) {
mHelper.reconnectClients(whichClients);
}
protected String getScopes() {
return mHelper.getScopes();
}
protected boolean hasSignInError() {
return mHelper.hasSignInError();
}
protected ConnectionResult getSignInError() {
return mHelper.getSignInError();
}
protected void setSignInMessages(String signingInMessage, String signingOutMessage) {
mSigningInMessage = signingInMessage;
mSigningOutMessage = signingOutMessage;
}
public void setRoomId(String rid) {
mRoomId = rid;
}
public String getRoomId() {
return mRoomId;
}
@Override
public void onRealTimeMessageReceived(RealTimeMessage rtm) {
mListener.handleRealTimeMessage(rtm);
}
// Called when we are connected to the room. We're not ready to play yet! (maybe not everybody is connected yet).
@Override
public void onConnectedToRoom(Room room) {
Log.d("mab", "onConnectedToRoom.");
// get room ID, participants and my ID:
mRoomId = room.getRoomId();
mParticipants = room.getParticipants();
mMyId = room.getParticipantId(getGamesClient().getCurrentPlayerId());
// print out the list of participants (for debug purposes)
Log.d("mab", "Room ID: " + mRoomId);
Log.d("mab", "My ID " + mMyId);
Log.d("mab", "<< CONNECTED TO ROOM>>");
Log.d("mab", " Number of Joined Participants: " + getNumJoinedParticipants());
}
// Called when we get disconnected from the room. We return to the main screen.
@Override
public void onDisconnectedFromRoom(Room room) {
mIsMultiplayer = false;
mRoomId = null;
showGameError("Disconnected from room");
}
@Override
public void onJoinedRoom(int statusCode, Room room) {
Log.d("mab", "onJoinedRoom(" + statusCode + ")");
if (room != null) { Log.d("mab", " roomId: " + room.getRoomId()); }
if (statusCode != GamesClient.STATUS_OK) {
mIsMultiplayer = false;
Log.e("mab", "*** Error: onJoinedRoom, status " + statusCode);
showGameError("Joined room unsuccessfully: " + statusCode);
return;
}
mRoomId = room.getRoomId();
// show the waiting room UI
showWaitingRoom(room);
}
// Called when we've successfully left the room (this happens a result of voluntarily leaving
// via a call to leaveRoom(). If we get disconnected, we get onDisconnectedFromRoom()).
@Override
public void onLeftRoom(int statusCode, String roomId) {
// we have left the room; return to main screen.
Log.d("mab", "onLeftRoom, code " + statusCode);
mRoomId = null; //????? right?
showMainMenu();
}
// Called when room is fully connected.
@Override
public void onRoomConnected(int statusCode, Room room) {
Log.d("mab", "onRoomConnected(" + statusCode + ")");
if (room != null) { Log.d("mab", " roomId: " + room.getRoomId()); }
if (statusCode != GamesClient.STATUS_OK) {
mIsMultiplayer = false;
Log.d("mab", "*** Error: onRoomConnected, status " + statusCode);
showGameError("Roon connected unsuccessfully: " + statusCode);
return;
}
mRoomId = room.getRoomId();
mParticipants = room.getParticipants(); // not sure if we need this here again, but shouldn't hurt (or maybe we want this ONLY here)
mIsMultiplayer = true;
// Set 1st player to take a turn
mCurrentlyPlayingIdx = 0;
// Start Game!
mListener.startGame();
}
// Called when room has been created
@Override
public void onRoomCreated(int statusCode, Room room) {
Log.d("mab", "onRoomCreated(" + statusCode + ")");
if (room != null) { Log.d("mab", " roomId: " + room.getRoomId()); }
if (statusCode != GamesClient.STATUS_OK) {
mIsMultiplayer = false;
Log.e("mab", "*** Error: onRoomCreated, status " + statusCode);
showGameError("Room not created successfully: " + statusCode);
return;
}
mRoomId = room.getRoomId();
// show the waiting room UI
showWaitingRoom(room);
}
// Called when we get an invitation to play a game. We react by showing that to the user.
@Override
public void onInvitationReceived(Invitation invitation) {
Log.d("mab", "ghFrag.onInvitationReceived()");
mListener.onInvitationReceived(invitation);
}
@Override
public void onSignInFailed() {
mListener.onSignInFailed();
}
@Override
public void onSignInSucceeded() {
// install invitation listener so we get notified if we receive an invitation to play a game.
getGamesClient().registerInvitationListener(this);
if (getInvitationId() != null) {
acceptInviteToRoom(getInvitationId());
return;
}
mListener.onSignInSucceeded();
}
// Accept the given invitation.
void acceptInviteToRoom(String invId) {
// accept the invitation
Log.d("mab", "Accepting invitation: " + invId);
keepScreenOn();
RoomConfig.Builder roomConfigBuilder = RoomConfig.builder(this);
roomConfigBuilder.setInvitationIdToAccept(invId)
.setMessageReceivedListener(this)
.setRoomStatusUpdateListener(this);
showWaitScreen();
getGamesClient().joinRoom(roomConfigBuilder.build());
}
// Sets the flag to keep this screen on. It's recommended to do that during the handshake when setting up a game, because if the screen turns off, the game will be cancelled.
void keepScreenOn() {
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
// Clears the flag that keeps the screen on.
void stopKeepingScreenOn() {
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
public void inviteFriends() {
// show list of invitable players
Intent intent = getGamesClient().getSelectPlayersIntent(1, 3);
showWaitScreen();
startActivityForResult(intent, RC_SELECT_PLAYERS);
}
// Leave the room.
void leaveRoom() {
Log.d("mab", "Leaving room.");
mIsMultiplayer = false;
stopKeepingScreenOn();
if (mRoomId != null) {
getGamesClient().leaveRoom(this, mRoomId);
mRoomId = null;
showWaitScreen();
} else {
showMainMenu();
}
}
// Show the waiting room UI to track the progress of other players as they enter the
// room and get connected.
void showWaitingRoom(Room room) {
Log.d("mab", "GHFrag.showWaitingRoom()");
mWaitRoomDismissedFromCode = false;
int minPlayers = MAX_NUM_PLAYERS; // This just means the "Start" menu item will never be enabled (waiting room will exit automatically once everyone has made a decision)
Intent i = getGamesClient().getRealTimeWaitingRoomIntent(room, minPlayers);
// show waiting room UI
getActivity().startActivityForResult(i, RC_WAITING_ROOM);
}
// Forcibly dismiss the waiting room UI (this is useful, for example, if we realize the
// game needs to start because someone else is starting to play).
void dismissWaitingRoom() {
mWaitRoomDismissedFromCode = true;
getActivity().finishActivity(RC_WAITING_ROOM); //getActivity() ?????
}
// Show error message about game being cancelled and return to main screen.
void showGameError(String msg) {
showAlert("Error", "Game Error: " + msg);
showMainMenu();
}
private void showMainMenu() {
mListener.showMainMenu();
}
private void showWaitScreen() {
mListener.showWaitScreen();
}
}
public class MainActivity extends FragmentActivity implements MainMenuFragment.Listener, PlayFragment.Listener, GameHelperFragmentListener, AlertDialogFragmentListener {
public static final String MAIN_MENU_FRAGMENT = "MainMenuFragment";
public static final String PLAY_FRAGMENT = "PlayFragment";
public static final String WAIT_FRAGMENT = "WaitFragment";
// Fragments
MainMenuFragment mMainMenuFragment;
PlayFragment mPlayFragment;
WaitFragment mWaitFragment;
GameHelperFragment gameHelperFragment = null;
String mIncomingInvitationId = null;
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d("mab", "MainActivity.onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Add Headless Fragment (if not already retained)
gameHelperFragment = (GameHelperFragment) getSupportFragmentManager().findFragmentByTag("GameHelperFragment");
if (gameHelperFragment == null) {
Log.d("mab", this + ": Existing fragment not found.!!!");
gameHelperFragment = new GameHelperFragment();
gameHelperFragment.setSignInMessages("Signing in with Google", "Signing out");
getSupportFragmentManager().beginTransaction().add(gameHelperFragment, "GameHelperFragment").commit();
} else {
Log.d("mab", this + ": Existing fragment found.!!!");
}
}
@Override
public void onSignInFailed() {
Log.d("mab", "MainActivity.onSignInFailed()");
if (mMainMenuFragment != null) {
mMainMenuFragment.updateUi();
}
}
@Override
public void onSignInSucceeded() {
Log.d("mab", "MainActivity.onSignInSuccedded()");
if (mMainMenuFragment != null) {
mMainMenuFragment.updateUi();
}
}
@Override
public void onSignInButtonClicked() {
Log.d("mab", "MainActivity.onSignInButtonClicked()");
// start the sign-in flow
beginUserInitiatedSignIn();
}
@Override
public void onSignOutButtonClicked() {
Log.d("mab", "MainActivity.onSignOutButtonClicked()");
signOut();
if (mMainMenuFragment != null) {
mMainMenuFragment.updateUi();
}
}
@Override
public void onInvitationReceived(Invitation invitation) {
mIncomingInvitationId = invitation.getInvitationId();
// show accept/decline dialog box here.
String dispName = invitation.getInviter().getDisplayName();
DialogFragment alertInvitationReceived = AlertDialogFragment.newInstance("Invitation Received", dispName +
" is inviting you to play Yahtzee Blast.", "Accept", "Decline", null);
alertInvitationReceived.show(getSupportFragmentManager(), DLG_INVITATION_RECVD);
}
@Override
protected void onPause() {
Log.d("mab", "MainActivity.onPause()");
super.onPause();
}
@Override
protected void onStop() {
Log.d("mab", "MainActivity.onStop()");
super.onStop();
}
@Override
protected void onStart() {
Log.d("mab", "MainActivity.onStart()");
super.onStart();
}
@Override
protected void onResume() {
Log.d("mab", "MainActivity.onResume()");
super.onResume();
}
@Override
protected void onDestroy() {
Log.d("mab", "MainActivity.onDestroy()");
super.onDestroy();
mHelper = null;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("mIncomingInvitationId", mIncomingInvitationId); // ? need this ?
}
@Override
public void onInviteFriendsClicked() {
Log.d("mab", "MainActivity.onInviteFriendsClicked()");
gameHelperFragment.inviteFriends();
}
@Override
public void onSeeAllInvitationsClicked() {
Log.d("mab", "MainActivity.onSeeAllInvitationsClicked()");
gameHelperFragment.seeAllInvitations();
}
@Override
public void onActivityResult(int requestCode, int responseCode, Intent intent) {
Log.d("mab", this + ": onActivityResult(requestCode: " + requestCode + ", responseCode: " + responseCode + ")");
super.onActivityResult(requestCode, responseCode, intent);
// Call GameHelper's onActivityResult in case this result pertains to it
gameHelperFragment.onActivityResult(requestCode, responseCode, intent);
}
public void onAlertDialogFragmentPositiveClicked(String tag) {
Log.d("mab", "MainActivity.onAlertDialogFragmentPositiveClicked(" + tag + ")");
if (tag == DLG_INVITATION_RECVD) {
gameHelperFragment.acceptInviteToRoom(mIncomingInvitationId);
}
}
// Called when we receive a real-time message from the network.
public void handleRealTimeMessage(RealTimeMessage rtm) {
Log.d(TAG, "MainActivity.onRealTimeMessageReceived()");
// Handle it here...
}
// Headless Fragment Functions
private void setSignInMessages(String signingInMessage, String signingOutMessage) {
gameHelperFragment.setSignInMessages(signingInMessage, signingOutMessage);
}
private GamesClient getGamesClient() {
return gameHelperFragment.getGamesClient();
}
private String getInvitationId() {
return gameHelperFragment.getInvitationId();
}
private void beginUserInitiatedSignIn() {
gameHelperFragment.beginUserInitiatedSignIn();
}
private void signOut() {
gameHelperFragment.signOut();
}
private void showAlert(String message) {
gameHelperFragment.showAlert(message);
}
private void showAlert(String title, String message) {
gameHelperFragment.showAlert(title, message);
}
public GameHelperFragment getGameHelperFragment() {
return gameHelperFragment;
}
@Override
public void showMainMenu() {
switchToFragment(MAIN_MENU_FRAGMENT, false);
}
@Override
public void showWaitScreen() {
switchToFragment(WAIT_FRAGMENT, false);
}
@Override
public void participantLeftAtIdx(int idx) {
// Handle here, if there's anything you need to do.
}
}