/** Sign out and disconnect from the APIs. */ public void signOut() { if (!mGoogleApiClient.isConnected()) { // nothing to do debugLog("signOut: was already disconnected, ignoring."); return; } // for Plus, "signing out" means clearing the default account and // then disconnecting if (0 != (mRequestedClients & CLIENT_PLUS)) { debugLog("Clearing default account on PlusClient."); Plus.AccountApi.clearDefaultAccount(mGoogleApiClient); } // For the games client, signing out means calling signOut and // disconnecting if (0 != (mRequestedClients & CLIENT_GAMES)) { debugLog("Signing out from the Google API Client."); Games.signOut(mGoogleApiClient); } // Ready to disconnect debugLog("Disconnecting client."); mConnectOnStart = false; mConnecting = false; mGoogleApiClient.disconnect(); }
/** Call this method from your Activity's onStart(). */ public void onStart(Activity act) { mActivity = act; mAppContext = act.getApplicationContext(); debugLog("onStart"); assertConfigured("onStart"); if (mConnectOnStart) { if (mGoogleApiClient.isConnected()) { Log.w(TAG, "GameHelper: client was already connected on onStart()"); } else { debugLog("Connecting client."); mConnecting = true; mGoogleApiClient.connect(); } } else { debugLog("Not attempting to connect becase mConnectOnStart=false"); debugLog("Instead, reporting a sign-in failure."); mHandler.postDelayed( new Runnable() { @Override public void run() { notifyListener(false); } }, 1000); } }
/** Called when we are disconnected from the Google API client. */ @Override public void onConnectionSuspended(int cause) { debugLog("onConnectionSuspended, cause=" + cause); disconnect(); mSignInFailureReason = null; debugLog("Making extraordinary call to onSignInFailed callback"); mConnecting = false; notifyListener(false); }
void connect() { if (mGoogleApiClient.isConnected()) { debugLog("Already connected."); return; } debugLog("Starting connection."); mConnecting = true; mInvitation = null; mTurnBasedMatch = null; mGoogleApiClient.connect(); }
/** * Handle activity result. Call this method from your Activity's onActivityResult callback. If the * activity result pertains to the sign-in process, processes it appropriately. */ public void onActivityResult(int requestCode, int responseCode, Intent intent) { debugLog( "onActivityResult: req=" + (requestCode == RC_RESOLVE ? "RC_RESOLVE" : String.valueOf(requestCode)) + ", resp=" + GameHelperUtils.activityResponseCodeToString(responseCode)); if (requestCode != RC_RESOLVE) { debugLog("onActivityResult: request code not meant for us. Ignoring."); return; } // no longer expecting a resolution mExpectingResolution = false; if (!mConnecting) { debugLog("onActivityResult: ignoring because we are not connecting."); return; } // We're coming back from an activity that was launched to resolve a // connection problem. For example, the sign-in UI. if (responseCode == Activity.RESULT_OK) { // Ready to try to connect again. debugLog("onAR: Resolution was RESULT_OK, so connecting current client again."); connect(); } else if (responseCode == GamesActivityResultCodes.RESULT_RECONNECT_REQUIRED) { debugLog("onAR: Resolution was RECONNECT_REQUIRED, so reconnecting."); connect(); } else if (responseCode == Activity.RESULT_CANCELED) { // User cancelled. debugLog("onAR: Got a cancellation result, so disconnecting."); mSignInCancelled = true; mConnectOnStart = false; mUserInitiatedSignIn = false; mSignInFailureReason = null; // cancelling is not a failure! mConnecting = false; mGoogleApiClient.disconnect(); // increment # of cancellations int prevCancellations = getSignInCancellations(); int newCancellations = incrementSignInCancellations(); debugLog( "onAR: # of cancellations " + prevCancellations + " --> " + newCancellations + ", max " + mMaxAutoSignInAttempts); notifyListener(false); } else { // Whatever the problem we were trying to solve, it was not // solved. So give up and show an error message. debugLog( "onAR: responseCode=" + GameHelperUtils.activityResponseCodeToString(responseCode) + ", so giving up."); giveUp(new SignInFailureReason(mConnectionResult.getErrorCode(), responseCode)); } }
/** Call this method from your Activity's onStop(). */ public void onStop() { debugLog("onStop"); assertConfigured("onStop"); if (mGoogleApiClient.isConnected()) { debugLog("Disconnecting client due to onStop"); mGoogleApiClient.disconnect(); } else { debugLog("Client already disconnected when we got onStop."); } mConnecting = false; mExpectingResolution = false; // let go of the Activity reference mActivity = null; }
void succeedSignIn() { debugLog("succeedSignIn"); mSignInFailureReason = null; mConnectOnStart = true; mUserInitiatedSignIn = false; mConnecting = false; notifyListener(true); }
public void disconnect() { if (mGoogleApiClient.isConnected()) { debugLog("Disconnecting client."); mGoogleApiClient.disconnect(); } else { Log.w(TAG, "disconnect() called when client was already disconnected."); } }
/** * Starts a user-initiated sign-in flow. This should be called when the user clicks on a "Sign In" * button. As a result, authentication/consent dialogs may show up. At the end of the process, the * GameHelperListener's onSignInSucceeded() or onSignInFailed() methods will be called. */ public void beginUserInitiatedSignIn() { debugLog("beginUserInitiatedSignIn: resetting attempt count."); resetSignInCancellations(); mSignInCancelled = false; mConnectOnStart = true; if (mGoogleApiClient.isConnected()) { // nothing to do logWarn( "beginUserInitiatedSignIn() called when already connected. " + "Calling listener directly to notify of success."); notifyListener(true); return; } else if (mConnecting) { logWarn( "beginUserInitiatedSignIn() called when already connecting. " + "Be patient! You can only call this method after you get an " + "onSignInSucceeded() or onSignInFailed() callback. Suggestion: disable " + "the sign-in button on startup and also when it's clicked, and re-enable " + "when you get the callback."); // ignore call (listener will get a callback when the connection // process finishes) return; } debugLog("Starting USER-INITIATED sign-in flow."); // indicate that user is actively trying to sign in (so we know to // resolve // connection problems by showing dialogs) mUserInitiatedSignIn = true; if (mConnectionResult != null) { // We have a pending connection result from a previous failure, so // start with that. debugLog("beginUserInitiatedSignIn: continuing pending sign-in flow."); mConnecting = true; resolveConnectionResult(); } else { // We don't have a pending connection result, so start anew. debugLog("beginUserInitiatedSignIn: starting new sign-in flow."); mConnecting = true; connect(); } }
/** Disconnects the API client, then connects again. */ public void reconnectClient() { if (!mGoogleApiClient.isConnected()) { Log.w(TAG, "reconnectClient() called when client is not connected."); // interpret it as a request to connect connect(); } else { debugLog("Reconnecting client."); mGoogleApiClient.reconnect(); } }
/** Called when we successfully obtain a connection to a client. */ @Override public void onConnected(Bundle connectionHint) { debugLog("onConnected: connected!"); if (connectionHint != null) { debugLog("onConnected: connection hint provided. Checking for invite."); Invitation inv = connectionHint.getParcelable(Multiplayer.EXTRA_INVITATION); if (inv != null && inv.getInvitationId() != null) { // retrieve and cache the invitation ID debugLog("onConnected: connection hint has a room invite!"); mInvitation = inv; debugLog("Invitation ID: " + mInvitation.getInvitationId()); } // Do we have any requests pending? mRequests = Games.Requests.getGameRequestsFromBundle(connectionHint); if (!mRequests.isEmpty()) { // We have requests in onConnected's connectionHint. debugLog("onConnected: connection hint has " + mRequests.size() + " request(s)"); } debugLog("onConnected: connection hint provided. Checking for TBMP game."); mTurnBasedMatch = connectionHint.getParcelable(Multiplayer.EXTRA_TURN_BASED_MATCH); } // we're good to go succeedSignIn(); }
/** * Attempts to resolve a connection failure. This will usually involve starting a UI flow that * lets the user give the appropriate consents necessary for sign-in to work. */ void resolveConnectionResult() { // Try to resolve the problem if (mExpectingResolution) { debugLog("We're already expecting the result of a previous resolution."); return; } if (mActivity == null) { debugLog("No need to resolve issue, activity does not exist anymore"); return; } debugLog("resolveConnectionResult: trying to resolve result: " + mConnectionResult); if (mConnectionResult.hasResolution()) { // This problem can be fixed. So let's try to fix it. debugLog("Result has resolution. Starting it."); try { // launch appropriate UI flow (which might, for example, be the // sign-in flow) mExpectingResolution = true; mConnectionResult.startResolutionForResult(mActivity, RC_RESOLVE); } catch (SendIntentException e) { // Try connecting again debugLog("SendIntentException, so connecting again."); connect(); } } else { // It's not a problem what we can solve, so give up and show an // error. debugLog("resolveConnectionResult: result has no resolution. Giving up."); giveUp(new SignInFailureReason(mConnectionResult.getErrorCode())); } }
void notifyListener(boolean success) { debugLog( "Notifying LISTENER of sign-in " + (success ? "SUCCESS" : mSignInFailureReason != null ? "FAILURE (error)" : "FAILURE (no error)")); if (mListener != null) { if (success) { mListener.onSignInSucceeded(); } else { mListener.onSignInFailed(); } } }
public void showFailureDialog() { if (mSignInFailureReason != null) { int errorCode = mSignInFailureReason.getServiceErrorCode(); int actResp = mSignInFailureReason.getActivityResultCode(); if (mShowErrorDialogs) { showFailureDialog(mActivity, actResp, errorCode); } else { debugLog( "Not showing error dialog because mShowErrorDialogs==false. " + "" + "Error was: " + mSignInFailureReason); } } }
/** * Performs setup on this GameHelper object. Call this from the onCreate() method of your * Activity. This will create the clients and do a few other initialization tasks. Next, * call @link{#onStart} from the onStart() method of your Activity. * * @param listener The listener to be notified of sign-in events. */ public void setup(GameHelperListener listener) { if (mSetupDone) { String error = "GameHelper: you cannot call GameHelper.setup() more than once!"; logError(error); throw new IllegalStateException(error); } mListener = listener; debugLog("Setup: requested clients: " + mRequestedClients); if (mGoogleApiClientBuilder == null) { // we don't have a builder yet, so create one createApiClientBuilder(); } mGoogleApiClient = mGoogleApiClientBuilder.build(); mGoogleApiClientBuilder = null; mSetupDone = true; }
// Not recommended for general use. This method forces the // "connect on start" flag // to a given state. This may be useful when using GameHelper in a // non-standard // sign-in flow. public void setConnectOnStart(boolean connectOnStart) { debugLog("Forcing mConnectOnStart=" + connectOnStart); mConnectOnStart = connectOnStart; }
/** Enables debug logging */ public void enableDebugLog(boolean enabled) { mDebugLog = enabled; if (enabled) { debugLog("Debug log enabled."); } }
/** Handles a connection failure. */ @Override public void onConnectionFailed(ConnectionResult result) { // save connection result for later reference debugLog("onConnectionFailed"); mConnectionResult = result; debugLog("Connection failure:"); debugLog(" - code: " + GameHelperUtils.errorCodeToString(mConnectionResult.getErrorCode())); debugLog(" - resolvable: " + mConnectionResult.hasResolution()); debugLog(" - details: " + mConnectionResult.toString()); int cancellations = getSignInCancellations(); boolean shouldResolve; if (mUserInitiatedSignIn) { debugLog("onConnectionFailed: WILL resolve because user initiated sign-in."); shouldResolve = true; } else if (mSignInCancelled) { debugLog("onConnectionFailed WILL NOT resolve (user already cancelled once)."); shouldResolve = false; } else if (cancellations < mMaxAutoSignInAttempts) { debugLog( "onConnectionFailed: WILL resolve because we have below the max# of " + "attempts, " + cancellations + " < " + mMaxAutoSignInAttempts); shouldResolve = true; } else { shouldResolve = false; debugLog( "onConnectionFailed: Will NOT resolve; not user-initiated and max attempts " + "reached: " + cancellations + " >= " + mMaxAutoSignInAttempts); } if (!shouldResolve) { // Fail and wait for the user to want to sign in. debugLog("onConnectionFailed: since we won't resolve, failing now."); mConnectionResult = result; mConnecting = false; notifyListener(false); return; } debugLog("onConnectionFailed: resolving problem..."); // Resolve the connection result. This usually means showing a dialog or // starting an Activity that will allow the user to give the appropriate // consents so that sign-in can be successful. resolveConnectionResult(); }