如果要存取 Google Play 遊戲服務功能,遊戲必須提供已登入玩家的帳戶。如果玩家未通過驗證,遊戲在呼叫 Google Play 遊戲服務 API 時可能會發生錯誤。本文件說明如何在遊戲中實作順暢的登入體驗。
實作玩家登入
GoogleSignInClient
類別是擷取目前已登入的玩家帳戶的主要進入點,如果玩家尚未在裝置上登入應用程式,則可讓玩家登入。
如要建立登入用戶端,請按照下列步驟操作:
如以下程式碼片段所示,請透過
GoogleSignInOptions
物件建立登入用戶端。如要在GoogleSignInOptions.Builder
中設定登入功能,您必須指定GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN
。GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
如果您想使用
SnapshotsClient
,請將.requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
新增至GoogleSignInOptions.Builder
,如以下程式碼片段所示:GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN) .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS) .build();
呼叫
GoogleSignIn.getClient()
方法,並傳入先前步驟中設定的選項。如果呼叫成功,Google Sign-In API 會傳回GoogleSignInClient
的例項。
檢查玩家是否已登入
您可以使用 GoogleSignIn.getLastSignedInAccount()
檢查帳戶是否已在目前裝置上登入,以及使用 GoogleSignIn.hasPermissions()
檢查帳戶是否已獲得所需權限。如果兩個條件都為 true,也就是 getLastSignedInAccount()
傳回非空值,而 hasPermissions()
傳回 true
,即使裝置處於離線狀態,您也可以安全地使用 getLastSignedInAccount()
傳回的帳戶。
執行自動登入
您可以呼叫 silentSignIn()
來擷取目前登入的玩家帳戶,並嘗試讓玩家登入,但不顯示使用者介面 (如果玩家已在其他裝置上成功登入您的應用程式)。
silentSignIn()
方法會傳回 Task<GoogleSignInAccount>
。在工作完成後,您可以將先前宣告的 GoogleSignInAccount
欄位設為工作傳回的登入帳戶,或設為 null
,表示沒有登入的使用者。
如果靜默登入嘗試失敗,您可以選擇傳送登入意圖,以便顯示登入使用者介面,如「執行互動式登入」一文所述。
由於活動不在前景時,已登入的播放器狀態可能會變更,因此建議您從活動的 onResume()
方法呼叫 silentSignIn()
。
如要執行無聲登入作業,請按照下列步驟操作:
- 在
GoogleSignInClient
上呼叫silentSignIn()
方法,即可啟動靜默登入流程。如果靜默登入成功,這個呼叫會傳回Task<GoogleSignInAccount>
物件,其中包含GoogleSignInAccount
。 - 覆寫
OnCompleteListener
,處理玩家登入的成功或失敗情況。- 如果登入工作成功,請呼叫
getResult()
,取得GoogleSignInAccount
物件。 - 如果登入失敗,您可以傳送登入意圖,啟動互動式登入流程。如需其他可用回呼事件監聽器的清單,請參閱 Tasks API 開發人員指南和
Task
API 參考資料。
- 如果登入工作成功,請呼叫
以下程式碼片段說明應用程式如何執行靜默登入:
private void signInSilently() { GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN; GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this); if (GoogleSignIn.hasPermissions(account, signInOptions.getScopeArray())) { // Already signed in. // The signed in account is stored in the 'account' variable. GoogleSignInAccount signedInAccount = account; } else { // Haven't been signed-in before. Try the silent sign-in first. GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOptions); signInClient .silentSignIn() .addOnCompleteListener( this, new OnCompleteListener<GoogleSignInAccount>() { @Override public void onComplete(@NonNull Task<GoogleSignInAccount> task) { if (task.isSuccessful()) { // The signed in account is stored in the task's result. GoogleSignInAccount signedInAccount = task.getResult(); } else { // Player will need to sign-in explicitly using via UI. // See [sign-in best practices](http://developers.google.com/games/services/checklist) for guidance on how and when to implement Interactive Sign-in, // and [Performing Interactive Sign-in](http://developers.google.com/games/services/android/signin#performing_interactive_sign-in) for details on how to implement // Interactive Sign-in. } } }); } } @Override protected void onResume() { super.onResume(); signInSilently(); }
如果靜默登入嘗試失敗,您可以呼叫 getException()
取得包含詳細狀態碼的 ApiException
。如果狀態碼為 CommonStatusCodes.SIGN_IN_REQUIRED
,表示玩家必須採取明確的動作才能登入。在這種情況下,應用程式應啟動互動式登入流程,詳情請參閱下一節。
執行互動式登入
如要透過玩家互動登入,應用程式必須啟動登入意圖。如果成功,Google Sign-In API 會顯示使用者介面,提示玩家輸入登入憑證。這種做法可簡化應用程式開發作業,因為登入活動會代替應用程式處理需要更新 Google Play 服務或顯示同意提示的情況。結果會透過 onActivityResult
回呼傳回。
如要以互動方式登入,請按照下列步驟操作:
在
GoogleSignInClient
上呼叫getSigninIntent()
,取得登入意圖,然後呼叫startActivity()
並傳入該意圖。以下程式碼片段將展示應用程式如何啟動互動式登入流程:private void startSignInIntent() { GoogleSignInClient signInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN); Intent intent = signInClient.getSignInIntent(); startActivityForResult(intent, RC_SIGN_IN); }
在
onActivityResult()
回呼中,處理傳回意圖的結果。- 如果登入結果成功,請從
GoogleSignInResult
取得GoogleSignInAccount
物件。 - 如果登入結果不成功,您應處理登入錯誤 (例如在快訊中顯示錯誤訊息)。以下程式碼片段說明應用程式如何處理玩家登入結果:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == RC_SIGN_IN) { GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); if (result.isSuccess()) { // The signed in account is stored in the result. GoogleSignInAccount signedInAccount = result.getSignInAccount(); } else { String message = result.getStatus().getStatusMessage(); if (message == null || message.isEmpty()) { message = getString(R.string.signin_other_error); } new AlertDialog.Builder(this).setMessage(message) .setNeutralButton(android.R.string.ok, null).show(); } } }
- 如果登入結果成功,請從
擷取播放器資訊
Google 登入 API 傳回的 GoogleSignInAccount
不含任何玩家資訊。如果您的遊戲使用玩家資訊 (例如玩家的顯示名稱和玩家 ID),您可以按照下列步驟擷取這些資訊。
- 呼叫
getPlayersClient()
方法,並將GoogleSignInAccount
做為參數傳入,取得PlayersClient
物件。 - 使用
PlayersClient
方法,以非同步方式載入含有玩家資訊的Player
物件。舉例來說,您可以呼叫getCurrentPlayer()
來載入目前登入的玩家。如果工作傳回的ApiException
狀態碼為SIGN_IN_REQUIRED
,表示玩家需要重新驗證。如要執行此操作,請呼叫GoogleSignInClient.getSignInIntent()
,以互動方式登入播放器。 - 如果工作成功傳回
Player
物件,您就可以呼叫Player
物件的相關方法,擷取特定玩家詳細資料 (例如getDisplayName()
或getPlayerId()
)。
提供登入按鈕
如要在遊戲中提供標準的 Google 登入按鈕,您可以使用下列任一方法:
- 在主要活動版面配置中加入
com.google.android.gms.common.SignInButton
;或 - 根據 Google 登入品牌宣傳指南設計自訂登入按鈕。
使用者按下登入按鈕後,遊戲應透過傳送登入意圖來啟動登入流程,如「執行互動式登入」一文所述。
這個程式碼片段說明如何在活動的 onCreate()
方法中加入登入按鈕。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_in); findViewById(R.id.sign_in_button).setOnClickListener(this); findViewById(R.id.sign_out_button).setOnClickListener(this); }
以下程式碼片段說明如何在使用者按下登入按鈕時傳送登入意圖。
@Override public void onClick(View view) { if (view.getId() == R.id.sign_in_button) { // start the asynchronous sign in flow startSignInIntent(); } else if (view.getId() == R.id.sign_out_button) { // sign out. signOut(); // show sign-in button, hide the sign-out button findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE); findViewById(R.id.sign_out_button).setVisibility(View.GONE); } }
顯示遊戲彈出式視窗
您可以使用 GamesClient
類別,在遊戲中顯示彈出式檢視畫面。舉例來說,您的遊戲可以顯示「歡迎回來」或「已解鎖成就」的彈出式視窗。如要讓 Google Play 遊戲服務在遊戲的檢視畫面中啟動彈出式視窗,請呼叫 setViewForPopups()
方法。您可以呼叫 setGravityForPopups()
,進一步自訂彈出式視窗在畫面中顯示的位置。
將玩家登出
您可以透過在 GoogleSignInClient
上呼叫 signOut()
方法,完成登出程序。
private void signOut() { GoogleSignInClient signInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN); signInClient.signOut().addOnCompleteListener(this, new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { // at this point, the user is signed out. } }); }