如何让Play游戏服务在启动时不自动登录?

时间:2022-06-19 20:46:39

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.

Google提供了BaseGameUtils库,并建议我们扩展其BaseGameActivity。但是,该课程使游戏在游戏开始时自动登录。如果玩家不想或不能连接到他的Google帐户,那么在游戏开始时这可能非常耗时。

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?

所以我不想要这个功能。相反,我想提供一个登录按钮。只有当他点击该按钮时才能连接播放器。从那时起,每次玩家开始游戏时,他都会自动连接到他的Google帐户,而无需点击任何按钮。我怎样才能做到这一点?

5 个解决方案

#1


44  

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

好吧,我已经弄清楚,默认情况下,最大自动登录时间是3,这意味着如果用户取消3次,那么应用程序将永远不会再次(除非您清除应用程序的数据)自动登录。它已存储在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

如果您不想扩展BaseGameActivity,那就是这样

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

Or if you extends BaseGameActivity

或者,如果您扩展BaseGameActivity

getGameHelper().setMaxAutoSignInAttempts(0);

#2


10  

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:

在GameHelper.java文件中有一个名为mConnectOnStart的布尔属性,默认情况下它设置为true。只需将其更改为false:

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:

您可以使用上述方法来自定义登录过程。就我而言,与你类似,我不想第一次自动连接。但如果用户之前登录过,我确实想要自动连接。为了实现这一点,我将位于BaseGameActivity类中的getGameHelper()方法更改为:

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.

每次从BaseGameActivity中的onStart()调用getGameHelper()方法。在上面的代码中,我刚刚添加了共享首选项,以便在用户之前登录时保留。并根据该情况调用setConnectOnStart()方法。

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.

最后,在用户启动登录过程后,不要忘记将“WAS_SIGNED_IN”(或者如果您使用不同名称定义的其他内容)共享首选项设置为true。您可以在BaseGameActivity类的onSignInSucceeded()方法中执行此操作。

Hope this will help you. Good luck.

希望这会帮助你。祝你好运。

#3


3  

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:

我是这样做的,我不知道这是不是最好的方法。我更改了GameHelper类,因此它将用户首选项存储在共享首选项中:

...
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

请参阅https://github.com/playgameservices/android-samples/blob/master/FAQ.txt第54行自动登录的原因

#4


1  

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

调用getGameHelper()。setConnectOnStart(false);来自onCreate

#5


0  

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

实际上,Google的代码与您在第二段中所讨论的完全一样。

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?

我想提供一个登录按钮。只有当他点击该按钮时才能连接播放器。从那时起,每次玩家开始游戏时,他都会自动连接到他的Google帐户,而无需点击任何按钮。我怎样才能做到这一点?

  1. The Helper.setup method creates the clients

    Helper.setup方法创建客户端

  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.

    onStart查看自动登录的内部布尔值。如果用户之前已连接(并且用户未注销,或断开连接时没有错误),则会尝试重新建立登录。

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

    如果启动成功连接,beginUserInitiatedSignIn将设置自动登录布尔值

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

    onStop只会优雅地终止连接,它不会重置布尔值

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.

因此,当应用程序启动时,用户看到登录过程的唯一方法是在按下按钮之前以某种方式调用beginUserInitiatedSignIn。

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.

确保您的beginUserInitiatedSignIn不在您的onStart方法中,除非您单击登录按钮且未登录用户之外的任何其他方式,否则不会调用它。

 @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

来自BaseGameUtil类

/** * 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)

/ ** *游戏的基类示例。此实现负责设置* GamesClient对象并管理其生命周期。子类只需要覆盖@link {#onSignInSucceeded}和@link {#onSignInFailed}抽象*方法。要在用户单击登录*按钮时启动登录流程,子类应调用@link {#beginUserInitiatedSignIn}。默认情况下,*此类仅实例化GamesClient对象。如果还需要PlusClient或* AppStateClient对象,请调用BaseGameActivity(int)*构造函数并指定所请求的客户端。例如,要请求* PlusClient和GamesClient,请使用BaseGameActivity(CLIENT_GAMES | CLIENT_PLUS)。 *要请求所有可用的客户端,请使用BaseGameActivity(CLIENT_ALL)。 *或者,您也可以通过* @link {#setRequestedClients}指定所请求的客户端,但必须在调用@link {#onCreate} *之前执行此操作,否则调用将无效。 * * @author Bruno Oliveira(谷歌)

#1


44  

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

好吧,我已经弄清楚,默认情况下,最大自动登录时间是3,这意味着如果用户取消3次,那么应用程序将永远不会再次(除非您清除应用程序的数据)自动登录。它已存储在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

如果您不想扩展BaseGameActivity,那就是这样

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

Or if you extends BaseGameActivity

或者,如果您扩展BaseGameActivity

getGameHelper().setMaxAutoSignInAttempts(0);

#2


10  

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:

在GameHelper.java文件中有一个名为mConnectOnStart的布尔属性,默认情况下它设置为true。只需将其更改为false:

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:

您可以使用上述方法来自定义登录过程。就我而言,与你类似,我不想第一次自动连接。但如果用户之前登录过,我确实想要自动连接。为了实现这一点,我将位于BaseGameActivity类中的getGameHelper()方法更改为:

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.

每次从BaseGameActivity中的onStart()调用getGameHelper()方法。在上面的代码中,我刚刚添加了共享首选项,以便在用户之前登录时保留。并根据该情况调用setConnectOnStart()方法。

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.

最后,在用户启动登录过程后,不要忘记将“WAS_SIGNED_IN”(或者如果您使用不同名称定义的其他内容)共享首选项设置为true。您可以在BaseGameActivity类的onSignInSucceeded()方法中执行此操作。

Hope this will help you. Good luck.

希望这会帮助你。祝你好运。

#3


3  

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:

我是这样做的,我不知道这是不是最好的方法。我更改了GameHelper类,因此它将用户首选项存储在共享首选项中:

...
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

请参阅https://github.com/playgameservices/android-samples/blob/master/FAQ.txt第54行自动登录的原因

#4


1  

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

调用getGameHelper()。setConnectOnStart(false);来自onCreate

#5


0  

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

实际上,Google的代码与您在第二段中所讨论的完全一样。

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?

我想提供一个登录按钮。只有当他点击该按钮时才能连接播放器。从那时起,每次玩家开始游戏时,他都会自动连接到他的Google帐户,而无需点击任何按钮。我怎样才能做到这一点?

  1. The Helper.setup method creates the clients

    Helper.setup方法创建客户端

  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.

    onStart查看自动登录的内部布尔值。如果用户之前已连接(并且用户未注销,或断开连接时没有错误),则会尝试重新建立登录。

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

    如果启动成功连接,beginUserInitiatedSignIn将设置自动登录布尔值

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

    onStop只会优雅地终止连接,它不会重置布尔值

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.

因此,当应用程序启动时,用户看到登录过程的唯一方法是在按下按钮之前以某种方式调用beginUserInitiatedSignIn。

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.

确保您的beginUserInitiatedSignIn不在您的onStart方法中,除非您单击登录按钮且未登录用户之外的任何其他方式,否则不会调用它。

 @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

来自BaseGameUtil类

/** * 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)

/ ** *游戏的基类示例。此实现负责设置* GamesClient对象并管理其生命周期。子类只需要覆盖@link {#onSignInSucceeded}和@link {#onSignInFailed}抽象*方法。要在用户单击登录*按钮时启动登录流程,子类应调用@link {#beginUserInitiatedSignIn}。默认情况下,*此类仅实例化GamesClient对象。如果还需要PlusClient或* AppStateClient对象,请调用BaseGameActivity(int)*构造函数并指定所请求的客户端。例如,要请求* PlusClient和GamesClient,请使用BaseGameActivity(CLIENT_GAMES | CLIENT_PLUS)。 *要请求所有可用的客户端,请使用BaseGameActivity(CLIENT_ALL)。 *或者,您也可以通过* @link {#setRequestedClients}指定所请求的客户端,但必须在调用@link {#onCreate} *之前执行此操作,否则调用将无效。 * * @author Bruno Oliveira(谷歌)