最近项目需要接入Google Games登录,按照Google官方建议,我们选择了Google Service SDK V10.2.0版本。但在接入Google Games Api时,却发生了些不愉快的事情。
Google的官方教程
Google Api 初始化
// Defaults to Games Lite scope, no server component
GoogleSignInOptions gso = new
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN).build();
// OR for apps with a server component
GoogleSignInOptions gso = new
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestServerAuthCode(SERVER_CLIENT_ID)
.build();
// OR for developers who need real user Identity
GoogleSignInOptions gso = new
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestEmail()
.build();
// Build the api client.
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Games.API)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addConnectionCallbacks(this)
.build();
}
Google Api 连接
mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
Google登录成功后的逻辑
@Override
public void onConnected(Bundle connectionHint) {
if (mGoogleApiClient.hasConnectedApi(Games.API)) {
Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient).setResultCallback(
new ResultCallback() {
@Override
public void onResult(
@NonNull GoogleSignInResult googleSignInResult) {
if (googleSignInResult.isSuccess()) {
onSignedIn(googleSignInResult.getSignInAccount(),
connectionHint);
} else {
Log.e(TAG, "Error with silentSignIn: " +
googleSignInResult.getStatus());
// Don't show a message here, this only happens
// when the user can be authenticated, but needs
// to accept consent requests.
handleSignOut();
}
}
}
);
} else {
handleSignOut();
}
}
Google提供的方法很简单直接,但是这段实例代码存在的问题是:
mApiClient.hasConnectedApi(Games.API)
一直返回false!!!
最初的解决方案:
通过打印日志,我发现,虽然此时mApiClient.hasConnectedApi(Games.API)返回false,但是
mApiClient.hasConnectedApi(Auth.GoogleSignInApi)返回的是true。
所以最开始时,我将上面的条件改成了mApiClient.hasConnectedApi(Auth.GoogleSignInApi),但是这个问题又来了,获取此时获取ServerAuthCode失败了,原因是:[SIGN_IN_REQUIRED]
看到这个状态,我突然想到了一个新的解决方案。
最终的解决方案:
由于这个SIGN_IN_REQUIRED错误码的启示,我发现可以将onConnected函数中代码改成这样:
@Override
public void onConnected(@Nullable Bundle bundle) {
ConnectionResult result = mApiClient.getConnectionResult(Games.API);
if (!result.isSuccess()) {
onConnectionFailed(result);
} else {
//TODO 做你想要做的事情
}
}
一些可能的疑惑
看到这里,有人会建议,为什么不在第一个解决方法中甚至一开始时就使用google提供的这个方法登录呢?
private void handleSignin() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
为什么不呢?
问题很简单:
就是每次调用这个方法,都会弹出一个半透明的Activity,感觉很诡异。