Domanda

Google provides the BaseGameUtils library, and recommend us to extends its BaseGameActivity. However, this class makes the game automatically sign in whenever the game is started. If the player does not want to or cannot connect to his Google account, this can be very time consuming at the beginning of the game.

So I dont' want this feature. Instead, I want to provide a sign in button. The player is connected only when he click that button. And from that point on, every time the player starts the game, he is automatically connected to his Google account without clicking any button. How can I do this?

È stato utile?

Soluzione

OK, I have figured it out, by default, the maximum auto sign-in times is 3, which means if the user cancels 3 times, then the app will never again (unless you clear the app's data) automatically sign in. It's stored in GameHelper.java

 // Should we start the flow to sign the user in automatically on startup? If so, up to
 // how many times in the life of the application?
 static final int DEFAULT_MAX_SIGN_IN_ATTEMPTS = 3;
 int mMaxAutoSignInAttempts = DEFAULT_MAX_SIGN_IN_ATTEMPTS;

And it also provides a function to set this maximum number

public void setMaxAutoSignInAttempts(int max) {
        mMaxAutoSignInAttempts = max;
}

So if you don't want any automatic signing-in attempt at all, just call this function

This is if you don't want to extends BaseGameActivity

gameHelper = new GameHelper(this, GameHelper.CLIENT_GAMES);
gameHelper.enableDebugLog(true);
gameHelper.setup(this);
gameHelper.setMaxAutoSignInAttempts(0);

Or if you extends BaseGameActivity

getGameHelper().setMaxAutoSignInAttempts(0);

Altri suggerimenti

In the GameHelper.java file there is a boolean attribute called mConnectOnStart that by default it is set to true. Just change it to false instead:

boolean mConnectOnStart = false;

Additionally, there is a method provided for managing this attribute from the outside of the class:

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

You can use the method above in order to customize your sign in process. In my case, similar to you, I don't want to auto connect the very first time. But if the user was signed in before, I do want to auto connect. To make this possible, I changed the getGameHelper() method that is located in the BaseGameActivity class to this:

public GameHelper getGameHelper() {
    if (mHelper == null) {
        mHelper = new GameHelper(this, mRequestedClients);
        mHelper.enableDebugLog(mDebugLog);

        googlePlaySharedPref = getSharedPreferences("GOOGLE_PLAY",
                Context.MODE_PRIVATE);
        boolean wasSignedIn = googlePlaySharedPref.getBoolean("WAS_SIGNED_IN", false);
        mHelper.setConnectOnStart(wasSignedIn);
    }
    return mHelper;
}

Every time, getGameHelper() method is called from onStart() in BaseGameActivity. In the code above, I just added the shared preference to keep if the user was signed in before. And called the setConnectOnStart() method according to that case.

Finally, don't forget to set the "WAS_SIGNED_IN" (or something else if you defined with different name) shared preference to true after user initiated sign in process. You can do this in the onSignInSucceeded() method in the BaseGameActivity class.

Hope this will help you. Good luck.

I did it like this, I don't know if this is the best way to do it. I changed the GameHelper class so it stores the user preference in the Shared Preferences:

...
public class GameHelper implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    ....

    // Whether to automatically try to sign in on onStart(). We only set this
    // to true when the sign-in process fails or the user explicitly signs out.
    // We set it back to false when the user initiates the sign in process.
    boolean mConnectOnStart = false;

    ...    

    /** Call this method from your Activity's onStart(). */
    public void onStart(Activity act) {
        mActivity = act;
        mAppContext = act.getApplicationContext();

        debugLog("onStart");
        assertConfigured("onStart");
        SharedPreferences sp = mAppContext.getSharedPreferences(GAMEHELPER_SHARED_PREFS, Context.MODE_PRIVATE);
        mConnectOnStart = sp.getBoolean(KEY_AUTO_SIGN_IN, false);
        if (mConnectOnStart) {

        ...
    }

    ... 

    /** Sign out and disconnect from the APIs. */
    public void signOut() {

        ...

        // Ready to disconnect
        debugLog("Disconnecting client.");
        mConnectOnStart = false;
        SharedPreferences.Editor editor = mAppContext.getSharedPreferences(GAMEHELPER_SHARED_PREFS, Context.MODE_PRIVATE).edit();
        editor.putBoolean(KEY_AUTO_SIGN_IN, false);
        editor.commit();
        mConnecting = false;
        mGoogleApiClient.disconnect();
    }

    ...

    /**
     * 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;
        SharedPreferences.Editor editor = mAppContext.getSharedPreferences(GAMEHELPER_SHARED_PREFS, Context.MODE_PRIVATE).edit();
        editor.putBoolean(KEY_AUTO_SIGN_IN, true);
        editor.commit();
        if (mGoogleApiClient.isConnected()) {

        ...
    }

    ...

    private final String GAMEHELPER_SHARED_PREFS = "GAMEHELPER_SHARED_PREFS";
    private final String KEY_SIGN_IN_CANCELLATIONS = "KEY_SIGN_IN_CANCELLATIONS";
    private final String KEY_AUTO_SIGN_IN = "KEY_AUTO_SIGN_IN";

    ...

}

See https://github.com/playgameservices/android-samples/blob/master/FAQ.txt line 54 why you sign in automatically

Call getGameHelper().setConnectOnStart(false); from onCreate

Actually, the code from Google works exactly like you are talking about in the second paragraph.

I want to provide a sign in button. The player is connected only when he click that button. And from that point on, every time the player starts the game, he is automatically connected to his Google account without clicking any button. How can I do this?

  1. The Helper.setup method creates the clients

  2. onStart looks at an internal boolean for auto-sign-in. If the user was previously connected (and user did not sign out, or there was no error in disconnecting) then it will try to re-establish sign in.

  3. beginUserInitiatedSignIn will set the auto-sign-in boolean if a successful connection is initiated

  4. onStop will only terminate the connections gracefully, it does not reset the boolean

So the only way that the user sees the sign in process when your app starts, is if beginUserInitiatedSignIn is somehow called before pushing a button.

Make sure your beginUserInitiatedSignIn is not in your onStart method, nor is it called except by any other means than when your sign-in button is clicked and the User is NOT signed in.

 @Override
protected void onCreate(Bundle b) {
    super.onCreate(b);
    mHelper = new GameHelper(this);
    if (mDebugLog) {
        mHelper.enableDebugLog(mDebugLog, mDebugTag);
    }
    mHelper.setup(this, mRequestedClients, mAdditionalScopes);
}

@Override
protected void onStart() {
    super.onStart();
    mHelper.onStart(this);
}

@Override
protected void onStop() {
    super.onStop();
    mHelper.onStop();
}


protected void beginUserInitiatedSignIn() {
    mHelper.beginUserInitiatedSignIn();
}

From the BaseGameUtil class

/** * Example base class for games. This implementation takes care of setting up * the GamesClient object and managing its lifecycle. Subclasses only need to * override the @link{#onSignInSucceeded} and @link{#onSignInFailed} abstract * methods. To initiate the sign-in flow when the user clicks the sign-in * button, subclasses should call @link{#beginUserInitiatedSignIn}. By default, * this class only instantiates the GamesClient object. If the PlusClient or * AppStateClient objects are also wanted, call the BaseGameActivity(int) * constructor and specify the requested clients. For example, to request * PlusClient and GamesClient, use BaseGameActivity(CLIENT_GAMES | CLIENT_PLUS). * To request all available clients, use BaseGameActivity(CLIENT_ALL). * Alternatively, you can also specify the requested clients via * @link{#setRequestedClients}, but you must do so before @link{#onCreate} * gets called, otherwise the call will have no effect. * * @author Bruno Oliveira (Google)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top