https://developers.google.com/identity/one-tap/android/get-started
그간은 firebase 에서 지원하는 구글 로그인만 보고 있었는데, 오늘은 은인(?)을 만나게 되어 다른거 하나를 알게 되었다. 구글에서 말하는 로그인 / 가입 방식... 이걸 이용하면 웹 사이트 운영시에는 도움이 될 것 같기도 하다.
2024.10.16 다시 찾아 본 글에서 이제는 더 이상 one tap login 을 사용할 수 없을 듯 합니다.
저 자료를 보면서 구현을 해 보았다. 제일 먼저 구현할 부분은 gradle 파일에 설정하기
dependencies { ... implementation 'com.google.android.gms:play-services-auth:20.0.1' }
가이드에 나와있는데로... 그 다음은 API 활용을 위해서 cloud 에 사용자 인증정보를 추가 하고 클라이언트ID을 받아서 챙겨 두자. 등록할 때 앱의 package 이름 그리고 SHA-1 디지털지문이 필요하므로 이것도 반드시 기억.여기서 주의할 부분을 찾았다. 가이드에 나와 있는 부분인데, 간과하고 넘어갔더니.
Google API 콘솔 프로젝트 설정
에서 프로젝트 열기 API 콘솔을 , 또는 당신이 아직없는 경우 프로젝트를 만듭니다.OAuth 동의 화면 페이지에서 모든 정보가 완전하고 정확한지 확인하십시오. 특히 앱의 개인정보 보호정책 및 서비스 약관의 URL을 지정했는지 확인하세요.자격 증명 페이지에서 앱에 대한 Android 클라이언트 ID가 아직 없는 경우 생성합니다. 앱의 패키지 이름과 SHA-1 서명을 지정해야 합니다.자격 증명 페이지에서 웹 애플리케이션 클라이언트 ID가 아직 없는 경우 생성합니다. 승인된 JavaScript 출처 및 승인된 리디렉션 URI 필드를 비워 둘 수 있습니다. 이 클라이언트 ID는 인증 백엔드 서버를 나타냅니다. (서버에서 Google API를 호출할 때 이 클라이언트 ID를 사용하지만 사용하지 않더라도 필요합니다.)
내가 안드로이드앱을 개발 한다고 해서 안드로이드 앱용 client id 을 만들어야 하는 게 아니였다. 그래서 수정본에서는 다음과 같이 구성을 만들었다.
위 가이드의 설명처럼 자바스크립트 원본 URI나 승인된 리디렉션 URI 등은 입력하지 않아도 된다. 잘 보고 따라 하시길...
import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.content.IntentSender; import android.os.Bundle; import android.util.Log; import com.google.android.gms.auth.api.identity.BeginSignInRequest; import com.google.android.gms.auth.api.identity.BeginSignInResult; import com.google.android.gms.auth.api.identity.Identity; import com.google.android.gms.auth.api.identity.SignInClient; import com.google.android.gms.auth.api.identity.SignInCredential; import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.CommonStatusCodes; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; public class MainActivity2 extends AppCompatActivity { private static final int REQ_ONE_TAP = 100; private static final String TAG = "MainActivity"; boolean showOneTapUI = false ; private SignInClient oneTapClient; private BeginSignInRequest signInRequest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); oneTapClient = Identity.getSignInClient(this); signInRequest = BeginSignInRequest.builder() .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder() .setSupported(true) .build()) .setGoogleIdTokenRequestOptions(BeginSignInRequest.GoogleIdTokenRequestOptions.builder() .setSupported(true) // Your server's client ID, not your Android client ID. .setServerClientId(getString(R.string.default_web_client_id)) // Only show accounts previously used to sign in. .setFilterByAuthorizedAccounts(true) .build()) // Automatically sign in when exactly one credential is retrieved. .setAutoSelectEnabled(true) .build(); oneTapClient.beginSignIn(signInRequest) .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() { @Override public void onSuccess(BeginSignInResult result) { try { Log.e(TAG, "onSuccess..................."); startIntentSenderForResult( result.getPendingIntent().getIntentSender(), REQ_ONE_TAP, null, 0, 0, 0); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage()); } } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // No saved credentials found. Launch the One Tap sign-up flow, or // do nothing and continue presenting the signed-out UI. Log.e(TAG, e.getLocalizedMessage()); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQ_ONE_TAP: try { SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data); String idToken = credential.getGoogleIdToken(); String username = credential.getId(); String password = credential.getPassword(); if (idToken != null) { // Got an ID token from Google. Use it to authenticate // with your backend. Log.e(TAG, "Got ID token."); } else if (password != null) { // Got a saved username and password. Use them to authenticate // with your backend. Log.e(TAG, "Got password."); } } catch (ApiException e) { switch (e.getStatusCode()) { case CommonStatusCodes.CANCELED: Log.e(TAG, "One-tap dialog was closed."); // Don't re-prompt the user. showOneTapUI = false; break; case CommonStatusCodes.NETWORK_ERROR: Log.e(TAG, "One-tap encountered a network error."); // Try again or just ignore. break; default: Log.e(TAG, "Couldn't get credential from result." + e.getLocalizedMessage()); break; } } break; } } @Override public void onBackPressed() { super.onBackPressed(); oneTapClient.signOut(); } }
그 다음은 가이드에 나와있는 코드 일부를 뽑아서 나의 코드에 넣기... 설명은 oneTapClient 을 생성하고 signInRequest 을 build하고 oneTapClient.beginSignIn 을 통해서 호출하면 실행이 된다는 것이다. 여기서 발견한 것은 가이드에 오타(?)가 있는 것만 같은 생각이 들었다.
가이드에서는 oneTapClient.beginSignIn( signUpRequest ) 라고 되어 있으나, 코틀린 예제는 다르다. 아마도 오타(?)일 것 같은 생각이 든다. 뭐 암튼... 실행해 보면 다음 처럼 볼 수 있다.
앱을 실행해 보면 구글 One Tap 로그인을 할 수 있는 화면이 실행이 되었다. 다만, 저걸 클릭후 오류가 발생했는데...
Couldn't get credential from result.10: Developer console is not set up correctly
이런 오류를 만나게 되었다면, 위에서 설명한 것 처럼 웹 어플용 ID 을 설정해야 한다.
다른 메시지는 16: Cannot find a matching credential. 이런걸 만날 수 있다. 이 경우는 clound console 에
OAuth 2.0 클라이언트 ID가 등록 되지 않은 경우에 만날 수 있다.
또는 다음 링크와 같은 경우에도 만날 수 있다.
https://stackoverflow.com/questions/61768804/getting-16-cannot-find-a-matching-credential-when-doing-one-tap-sign-in-and-s
'모바일 앱(안드로이드)' 카테고리의 다른 글
안드로이드 앱 만들기 : image blur (이미지 흐리게) 처리 하기 (2) | 2022.01.25 |
---|---|
안드로이드 앱 admob 정책 위반 이야기 (2) (3) | 2022.01.22 |
안드로이드 앱 만들기 Kotlin 이 뭐야 ? (2) | 2022.01.18 |
안드로이드 앱 만들기 : 구글맵 최종 위치 표시 하기. (2) | 2022.01.11 |
안드로이드 앱 만들기 : qrscan , barcode 스캐너 (2) | 2022.01.10 |