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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22046530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:27:48  来源:igfitidea点击:

How can I make the Play Game Services not automatically sign in at the startup?

androidgoogle-play-servicesgoogle-play-games

提问by H?i Phong

Google provides the BaseGameUtilslibrary, 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 consumingat 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 帐户,而无需点击任何按钮。我怎样才能做到这一点?

回答by H?i Phong

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);

回答by osmangokalp

In the GameHelper.javafile there is a boolean attribute called mConnectOnStartthat by default it is set to true. Just change it to falseinstead:

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 BaseGameActivityclass to this:

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

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.

每次getGameHelper()都从onStart()in调用方法BaseGameActivity。在上面的代码中,我只是添加了共享首选项以在用户之前登录时保留。并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 BaseGameActivityclass.

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

Hope this will help you. Good luck.

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

回答by Stefan Braspenning

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.txtline 54 why you sign in automatically

请参阅https://github.com/playgameservices/android-samples/blob/master/FAQ.txt第 54 行为什么您会自动登录

回答by Крум Илиев

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

getGameHelper().setConnectOnStart(false);从 onCreate调用

回答by user2346305

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

  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

  1. Helper.setup 方法创建客户端

  2. onStart 查看用于自动登录的内部布尔值。如果用户之前已连接(并且用户没有退出,或者断开连接没有错误),那么它将尝试重新建立登录。

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

  4. 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} * 被调用之前这样做,否则调用将无效。* * @作者布鲁诺奥利维拉(谷歌)