您的遊戲必須提供已登入玩家的帳戶,才能使用 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 登入 API 會傳回GoogleSignInClient
的執行個體。
檢查玩家是否已登入
您可以透過 GoogleSignIn.getLastSignedInAccount()
檢查帳戶是否已在目前的裝置上登入,以及該帳戶是否已使用 GoogleSignIn.hasPermissions()
授予必要的權限。如果兩個條件都為 true (也就是 getLastSignedInAccount()
傳回非空值,而 hasPermissions()
傳回 true
),您可以放心使用從 getLastSignedInAccount()
回傳的帳戶,即使裝置處於離線狀態也沒問題。
執行靜音登入
您可以呼叫 silentSignIn()
以擷取目前登入的玩家帳戶,並且在玩家成功在其他裝置上登入應用程式時,嘗試使用不顯示使用者介面的玩家登入。
silentSignIn()
方法會傳回 Task<GoogleSignInAccount>
。工作完成後,您可以將先前宣告的 GoogleSignInAccount
欄位設為工作作為結果傳回的登入帳戶,或設為 null
,表示沒有已登入的使用者。
如果無訊息登入嘗試失敗,您可以選擇傳送登入意圖以顯示登入使用者介面,如執行互動式登入中所述。
由於已登入玩家的狀態在活動不在前景時可能會變更,因此建議您從活動的 onResume()
方法呼叫 silentSignIn()
。
如要以無訊息的方式登入,請按照下列步驟操作:
- 對
GoogleSignInClient
呼叫silentSignIn()
方法,以啟動靜音登入流程。 如果無訊息登入成功,此呼叫會傳回包含GoogleSignInAccount
的Task<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 Sign-In API 傳回的 GoogleSignInAccount
不含任何播放器資訊。如果您的遊戲使用玩家資訊 (例如玩家的顯示名稱和玩家 ID),您可以按照這些步驟擷取這項資訊。
- 呼叫
getPlayersClient()
方法並傳入GoogleSignInAccount
做為參數,以取得PlayersClient
物件。 - 使用
PlayersClient
方法以非同步方式載入包含玩家資訊的Player
物件。舉例來說,您可以呼叫getCurrentPlayer()
來載入目前登入的播放器。如果工作傳回狀態碼為SIGN_IN_REQUIRED
的ApiException
,表示玩家需要重新驗證。方法是呼叫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. } }); }