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

28

谷歌提供了BaseGameUtils库,并建议我们扩展其BaseGameActivity。但是,这个类会在游戏启动时自动登录。如果玩家不想或无法连接到他的谷歌账号,这可能非常耗时。

因此我不想使用这个功能。相反,我想提供一个登录按钮。只有当玩家点击该按钮时,他才能连接。从那时起,每次玩家启动游戏,他都会自动连接到他的谷歌账户,而不需要点击任何按钮。 我该怎么做?


1
你最近有没有遇到过来自Google Play Services API新版本的这个错误?如果你知道一些解决方法,请在评论中分享。 - tjPark
5个回答

44

好的,我已经弄清楚了,默认情况下,最大自动登录次数为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;

它还提供了一个设置这个最大数量的函数

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

如果您不想尝试自动登录,只需调用此函数。

这是当您不想扩展BaseGameActivity时的情况。

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

或者如果您扩展了BaseGameActivity

getGameHelper().setMaxAutoSignInAttempts(0);

11
谁会想要三次呢?一次已经足够了,两次就已经很烦人了。如果我在某个应用程序上看到它出现三次,我会认为这个应用程序的开发者来自地狱般的愚蠢,即使这不是他的设计。 - tjPark
1
@tjPark 我同意...我也遇到了这个问题,发现 DEFAULT_MAX_SIGN_IN_ATTEMPTS 被设置为 3 真的让我感到非常困惑。 - Alex Lockwood
感谢您提供的答案。如果我们将最大值设置为0,那么如果用户之前已经登录,它会自动将其签入吗?基本上,它是否实现了问题的第二部分,并且您将mConnectOnStart设置为什么? - Snake
我发现那些没有在手机上安装 Google Play 服务的玩家,主要是外国玩家或非三星手机的玩家,在登录过程中根本无法通过。如果三星手机允许您禁用、停止或卸载 Google Play 服务进行测试,那将是很好的,但这些选项在我的设备上都是灰色或不可用的。 - Androidcoder

10

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

boolean mConnectOnStart = false;

此外,还提供了一种从类外部管理此属性的方法:

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

您可以使用上述方法来自定义您的登录流程。 在我这种情况下,与您类似,我不想在第一次登录时自动连接。但是如果用户以前已登录,则希望自动连接。为了实现这一点,我将位于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;
}
每次从 BaseGameActivityonStart() 方法中调用 getGameHelper() 方法。在上面的代码中,我只是添加了共享偏好以保留用户之前是否已登录的信息,并根据该情况调用了 setConnectOnStart() 方法。
最后,请不要忘记在用户启动登录过程后将 "WAS_SIGNED_IN"(如果您使用不同名称定义了其他内容,则可以使用其他名称)共享偏好设置为 true。您可以在 BaseGameActivity 类中的 onSignInSucceeded() 方法中执行此操作。
希望这对您有所帮助。祝您好运。

3
我是这么做的,不知道这是否是最好的方法。我修改了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";

    ...

}

请查看https://github.com/playgameservices/android-samples/blob/master/FAQ.txt中第54行,了解为什么您会自动登录。

1

在 onCreate 中调用 getGameHelper().setConnectOnStart(false);


0

实际上,谷歌的代码与您在第二段所说的完全一样。

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

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

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

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

  4. onStop仅会优雅地终止连接,不会重置布尔值

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

确保您的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();
}

来自BaseGameUtil类

/** * 游戏的示例基类。此实现负责设置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}之前这样做,否则调用将无效。 * * 作者:Bruno Oliveira(Google)


我认为onStart或者setup()方法可以自动管理我们的登录过程(隐式调用beginUserInitiatedSignIn())。不管怎样,我已经找到了如何禁用这个过程,详见我的回答。 - Hải Phong
实际上,如果Google的代码完全按照他在第二段中所说的那样做,这个问题就不会存在了。 - luben
在初始版本的辅助库中,默认情况下是手动的。现在似乎默认情况下是自动的。 - David Ameller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接