Android 게임에서 로그인

Google Play 게임즈 서비스 기능에 액세스하려면 로그인한 플레이어의 계정을 게임에서 제공해야 합니다. 플레이어가 인증되지 않으면 Google Play 게임 서비스 API를 호출할 때 게임에 오류가 발생할 수 있습니다. 이 문서에서는 게임에서 원활한 로그인 환경을 구현하는 방법을 설명합니다.

플레이어 로그인 구현

GoogleSignInClient 클래스는 현재 로그인한 플레이어의 계정을 가져오고, 이전에 기기의 앱에서 로그인하지 않은 경우 플레이어를 로그인하는 기본 진입점입니다.

로그인 클라이언트를 만들려면 다음 단계를 따르세요.

  1. 다음 코드 스니펫과 같이 GoogleSignInOptions 객체를 통해 로그인 클라이언트를 만듭니다. 로그인을 구성하려면 GoogleSignInOptions.Builder에서 GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN를 지정해야 합니다.

    GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
  2. SnapshotsClient를 사용하려면 다음 코드 스니펫과 같이 GoogleSignInOptions.Builder.requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)를 추가합니다.

    GoogleSignInOptions  signInOptions =
        new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
            .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
            .build();
  3. GoogleSignIn.getClient() 메서드를 호출하고 이전 단계에서 구성한 옵션을 전달합니다. 호출이 성공하면 Google Sign-In API는 GoogleSignInClient 인스턴스를 반환합니다.

플레이어가 이미 로그인되어 있는지 확인

GoogleSignIn.getLastSignedInAccount()를 사용하여 현재 기기에서 계정이 이미 로그인되어 있는지 확인하고 GoogleSignIn.hasPermissions()를 사용하여 이 계정에 이미 필요한 권한이 부여되었는지 확인할 수 있습니다. 두 조건이 모두 참이면(즉, getLastSignedInAccount()가 null이 아닌 값을 반환하고 hasPermissions()true를 반환함) 기기가 오프라인 상태이더라도 getLastSignedInAccount()에서 반환된 계정을 안전하게 사용할 수 있습니다.

자동 로그인 실행

silentSignIn()를 호출하여 현재 로그인한 플레이어의 계정을 가져오고, 사용자가 다른 기기에서 앱에 로그인한 경우 사용자 인터페이스를 표시하지 않고 플레이어를 로그인해 볼 수 있습니다.

silentSignIn() 메서드는 Task<GoogleSignInAccount>을 반환합니다. 작업이 완료되면 앞에서 선언한 GoogleSignInAccount 필드를 작업이 결과로 반환하는 로그인 계정으로 설정하거나 로그인한 사용자가 없음을 나타내는 null로 설정합니다.

자동 로그인 시도가 실패하면 원하는 경우 상호작용이 가능한 로그인 실행에 설명된 대로 로그인 인텐트를 전송하여 로그인 사용자 인터페이스를 표시할 수 있습니다.

활동이 포그라운드에 있지 않을 때 로그인한 플레이어의 상태가 변경될 수 있으므로 활동의 onResume() 메서드에서 silentSignIn()를 호출하는 것이 좋습니다.

자동으로 로그인하려면 다음 단계를 따르세요.

  1. GoogleSignInClient에서 silentSignIn() 메서드를 호출하여 자동 로그인 흐름을 시작합니다. 이 호출은 자동 로그인이 성공하면 GoogleSignInAccount가 포함된 Task<GoogleSignInAccount> 객체를 반환합니다.
  2. 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 로그인 API는 플레이어에게 로그인 사용자 인증 정보를 입력하라는 메시지를 표시하는 사용자 인터페이스를 표시합니다. 이 접근 방식을 사용하면 앱 대신 Google Play 서비스를 업데이트하거나 동의 메시지를 표시해야 하는 등의 시나리오를 로그인 활동이 처리하므로 앱 개발이 간소화됩니다. 결과는 onActivityResult 콜백을 통해 반환됩니다.

대화형으로 로그인을 실행하려면 다음 단계를 따르세요.

  1. 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);
    }
  2. 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와 같은 플레이어 정보를 사용하는 경우 다음 단계에 따라 이 정보를 가져올 수 있습니다.

  1. getPlayersClient() 메서드를 호출하고 GoogleSignInAccount를 매개변수로 전달하여 PlayersClient 객체를 가져옵니다.
  2. PlayersClient 메서드를 사용하여 플레이어 정보가 포함된 Player 객체를 비동기식으로 로드합니다. 예를 들어 getCurrentPlayer()를 호출하여 현재 로그인한 플레이어를 로드할 수 있습니다. 작업이 상태 코드 SIGN_IN_REQUIRED와 함께 ApiException를 반환하면 플레이어를 다시 인증해야 함을 나타냅니다. 이렇게 하려면 GoogleSignInClient.getSignInIntent()를 호출하여 플레이어를 대화식으로 로그인합니다.
  3. 작업이 Player 객체를 성공적으로 반환하면 Player 객체의 메서드를 호출하여 특정 플레이어 세부정보 (예: getDisplayName() 또는 getPlayerId())를 가져올 수 있습니다.

로그인 버튼 제공

게임에 표준 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.
        }
      });
}