最近項目需要接入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<GoogleSignInResult>() {
@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,感覺很詭異。