๋ชฉ์ฐจ
๐ ๋ค์ด๊ฐ๊ธฐ ์ ์
์๋๋ก์ด๋ ์ฑ์ ๊ตฌ๊ธ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ค๊ณ ๊ณต์๋ฌธ์๋ถํฐ ๋ง์ด ๋ฌธ์๋ฅผ ์ฐพ์๋ณด์์ง๋ง ๋์ด์ ์ง์๋์ง ์๋ ๋ฐฉ์์ธ ์ํญ์ ๋ํ ๊ธ์ด ๋๋ถ๋ถ์ด์๋ค.
์ง์๋์ง ์๋๋ค๋ ๋ง์ ๋ณด๊ณ ์๋ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๊ณ , ์ด๋ป๊ฒ ๊ตฌํํด์ผํ ์ง ๋ง๋งํ๋ ์ฐธ์
๊ธฐ๋ฅ์ด ์ ์๋๋์ด์ ์ฐ์ ๊ตฌ๊ธ ๋ก๊ทธ์ธ ๊ตฌํ์ ์ํ ์์๋ฅผ ์ ๋ฆฌํด๋ณด์๋ค! ์ดํ ์ธ์ฆ ๊ด๋ฆฌ์๋ก ์ฝ๋๋ฅผ ๋ฐ๊พธ๋ฉฐ ๋ฆฌํํ ๋ง์ ํ ์์ ์ด๋ค.
์๋์ฒ๋ผ ์ํญ ๋ก๊ทธ์ธ์ ๊ตฌํํด๋ณด์~~
1๏ธโฃ ์ํญ ๋ก๊ทธ์ธ ํด๋ผ์ด์ธํธ ๊ตฌ์ฑํ๊ธฐ
์ฐ๋ฆฌ ์ฑ์์๋ Google ๋ก๊ทธ์ธ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ setGoogleIdTokenRequestOptions ( )์ ์ฌ์ฉํ์ฌ Google ID ํ ํฐ ์์ฒญ์ ์ฌ์ฉ ์ค์ ํ๊ณ ๊ตฌ์ฑํด์ฃผ๋ฉด ๋๋ค.
//์ํญ ๋ก๊ทธ์ธ ํด๋ผ์ด์ธํธ ๊ตฌ์ฑ
oneTapClient = Identity.getSignInClient(this)
signInRequest = BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
.setServerClientId(SERVER_CLIENT_ID)
.setFilterByAuthorizedAccounts(false)
.build()
)
.build()
- SignInClient๋ ๋ก๊ทธ์ธ api๋ฅผ ์ํ client์ด๋ค.
SignInClient๋ sign-in (๋ก๊ทธ์ธ) ๊ณผ sign-up (๋ฑ๋ก) ๋ ์๋๋ฆฌ์ค์์ ๊ฐ์ ํ๋ฆ์ ๊ณต์ ํ์ง๋ง BeginSignInRequest ์์๋ ๋ค๋ฅธ ์๋๋ฆฌ์ค๋ฅผ ์ ๊ณตํด์ผ๋ง ํ๋ค.
๐ฅ PasswordRequestOptions ๋ก ๊ตฌํ ์ ์ํญ ๋ก๊ทธ์ธ UI์ ๋์์ด ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ๋น๊ตํด๋ณด๊ธฐ
credential์ ๋ํ ์ค๋ช
์ฐ์ credential ์ด๋ผ๋ ๊ฐ๋
์ ์๊ณ ์๋์ ์ค๋ช
์ ๋ณด์
credential์ ์๊ฒฉ์ด ์๋์ง ์ฆ๋ช
ํ๊ธฐ ์ํ ์๋จ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
๋ก๊ทธ์ธ(sign-in), ๋ฑ๋ก(sign-up)์์ ๋ค๋ฅธ BeginSignInRequest๋ฅผ ์ฌ์ฉํ๋ค.
- ์กด์ฌํ๋ ์ฌ์ฉ์๋ ๋ก๊ทธ์ธํ๋ค.
๋ ์ข ๋ฅ์ credentials์ SignInCredential ์์ ์ง์ํ๋ค.
- credential์ ์ข ๋ฅ
1. Google Id token credential
2. Password credential
์ฌ์ฉ์์๊ฒ ์ ํ์ง๋ฅผ ์ฃผ๊ณ , ๋ก๊ทธ์ธ ๋น์จ์ ๋์ด๊ธฐ ์ํด์๋ Google ID token๊ณผ password credential์ ๋ชจ๋ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค๊ณ ํ๋ค.
1. ๋ง์ฝ username๊ณผ password ๋ก๊ทธ์ธ์ ์ ๊ณตํ๋ ค๋ฉด ์์ฒญ์ PasswordRequestOptions ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฑํ๋ค.
2. ๋ง์ฝ Google Id token์ ์ฌ์ฉํ ๋ก๊ทธ์ธ์ ์ ๊ณตํ๋ ค๋ฉด GoogleInTokenRequestOptions ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฑํ๋ค.
๋ก๊ทธ์ธ ์๋๋ฆฌ์ค๋ฅผ ์ํด GoogleIDTokenRequestOptions.Builder.setFilterByAuthorizedAccounts๋ฅผ true๋ก ์ค์ ํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ credential ๋ฆฌ์คํธ๊ฐ ๋ณด์ฌ์ง๊ธฐ ์ ์ ์ธ์ฆ๋ ์ ์๋ค.
ํจ๊ณผ : ์ด๋ฏธ ์ฑ์ ๋ฑ๋ก๋ ๊ณ์ ์ด ์กด์ฌํ๋ ์ฌ์ฉ์๊ฐ ์๋ก์ด ๊ณ์ ์ ์์ฑํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์๋ค.
BeginSignInRequest ๋ ๋ก๊ทธ์ธ ์๋์์ ๋ฐํ๋ credential์ด ์ ๊ทผ๊ฐ๋ฅํ ํ์ ์ธ์ง ํํฐ๋ง ํ๋๋ฐ ์ฌ์ฉ๋๋ค.
๊ฐ ์ฝ๋ ์ค๋ช
// 1. SignInClient๋ฅผ ์ด๊ธฐํํ๋ค.
//getSignInClient๋ google play service์์ ์ ๊ณต๋๋ฉฐ ์ํญ ๋ก๊ทธ์ธ์ ์ฌ์ฉํ๊ธฐ ์ํ client๋ฅผ ์์ฑํ๋ค.
oneTapClient = Identity.getSignInClient(this)
// 2. ์ํญ ๋ก๊ทธ์ธ์ ์์ํ๊ธฐ ์ํ ์์ฒญ์ ์์ฑํ๋ค.
signInRequest = BeginSignInRequest.builder() // -> ์๋ก์ด ์์ฒญ์ ๋ง๋ค๊ธฐ ์ํ ๋น๋ ๋ฐํ
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true) // -> google id token์ด ์ง์๋๋์ง ์ฌ๋ถ
.setServerClientId(SERVER_CLIENT_ID) // -> google cloud console์์ ์์ฑํ ์๋ฒ์ฉ Oauth 2.0 ํด๋ผ์ด์ธํธ ID
.setFilterByAuthorizedAccounts(false)
// ์ฌ์ฉ์๊ฐ ์ฑ์ ์ด๋ฏธ ๋ก๊ทธ์ธ๋์ด์๋ ๊ฒฝ์ฐ์๋ง ์ํญ ๋ก๊ทธ์ธ์ด ์๋ํ๋๋ก,
// true์ธ ๊ฒฝ์ฐ ๋ก๊ทธ์ธ๋์ด์์ง ์๋๋ผ๋ ์ํญ ๋ก๊ทธ์ธ ์๋ํ๋ค.
.build()
)
.build() // -> ์ค์ ํ์ต์
์ผ๋ก ์ต์ข
SignInRequest ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
2๏ธโฃ ๋ก๊ทธ์ธํ ์ฌ์ฉ์ ํ์ธ
๐ฅ ์ด ๊ณผ์ ์ ์ด๋ป๊ฒ ์งํ๋๋๊ฒ์ธ์ง ๋ ์ฐพ์๋ณด๊ธฐ
3๏ธโฃ ์ํญ ๋ก๊ทธ์ธ UI ํ์
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ์ง ์์๊ณ , ์ํญ ๋ก๊ทธ์ธ ์ฌ์ฉ์ ๊ฑฐ๋ถํ์ง ์์๋ค๋ฉด ํด๋ผ์ด์ธํธ ๊ฐ์ฒด์ beginSignIn ๋ฉ์๋๋ฅผ ํธ์ถํ๊ณ ๋ฐํ๋๋ Task์ ๋ฆฌ์ค๋๋ฅผ ์ฐ๊ฒฐํด์ค๋ค.
์ฌ์ฉ์์๊ฒ ์ ์ฅ๋ ์ฑ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๊ฐ ์์ ๋ ์ํญ ํด๋ผ์ด์ธํธ๋ ์ฑ๊ณต ๋ฆฌ์ค๋๋ฅผ ํธ์ถํ๋ค.
๐ฅ ์ฑ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ ?
์ฑ๊ณต ๋ฆฌ์ค๋์ task ๊ฒฐ๊ณผ์์ ๋๊ธฐ ์ค์ธ ์ธํ ํธ๋ฅผ ๊ฐ์ ธ์ startIntentSenderForResult( ) ์ ์ ๋ฌํ์ฌ ์ํญ ๋ก๊ทธ์ธ UI๋ฅผ ์์ํ๋ค.
์ฌ์ฉ์์๊ฒ ์ ์ฅ๋ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๊ฐ ์๋ ๊ฒฝ์ฐ ์ํญ ํด๋ผ์ด์ธํธ๋ ์คํจ ๋ฆฌ์ค๋๋ฅผ ํธ์ถํ๋ค. ๋ณ๋์ ์กฐ์น๋ ํ์ํ์ง ์๋ค.
์ฑ์ ๋ก๊ทธ์์ ํ๊ฒฝ์ ๊ณ์ ํ์ํด์ฃผ๋ฉด ๋๋ค.
binding.googleLoginBtn.setOnClickListener {
// Begin the One Tap sign-in flow
oneTapClient.beginSignIn(signInRequest)
.addOnSuccessListener(this) { result ->
try {
// Start the One Tap UI
startIntentSenderForResult(
result.pendingIntent.intentSender, REQ_ONE_TAP,
null, 0, 0, 0, null
)
} catch (e: IntentSender.SendIntentException) {
Log.e("Google", "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
.addOnFailureListener(this) { e ->
// Handle failure (no saved credentials found)
Log.d("Google", e.localizedMessage)
}
}
4๏ธโฃ ์ฌ์ฉ์ ์๋ต ์ฒ๋ฆฌ
์ํญ ๋ก๊ทธ์ธ ๋ฉ์์ง์ ๋ํ ์ฌ์ฉ์์ ์๋ต์ Activity์ onActivityResult ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ์ ๋ณด๊ณ ๋๋ค.
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ ์ ํํ ๊ฒฝ์ฐ ์ ์ฅ๋ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๊ฐ ๊ฒฐ๊ณผ์ ํ์๋๋ค.
์ฌ์ฉ์๊ฐ ์ํญ UI๋ฅผ ๋ซ๊ฑฐ๋ ๋ก๊ทธ์ธ์ ๊ฑฐ๋ถํ๋ฉด RESULT_CANCELED ์ฝ๋์ ํจ๊ป ๊ฒฐ๊ณผ๊ฐ ๋ฐํ๋๋ค. ์ด ๋๊ฐ์ง๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํด์ค์ผํ๋ค.
๊ฐ์ ธ์จ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ก ๋ก๊ทธ์ธ
์ฌ์ฉ์๊ฐ ์ฑ๊ณผ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ณต์ ํ๊ธฐ๋ก ์ ํํ ๊ฒฝ์ฐ onActivityResult ( )์ ์ธํ ํธ ๋ฐ์ดํฐ๋ฅผ ์ํญ ํด๋ผ์ด์ธํธ์ getSignInCredentialFromIntent( ) ๋ฉ์๋์ ์ ๋ฌํ์ฌ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ฒ์ํ ์ ์๋ค.
์ฌ์ฉ์๊ฐ ์ฑ๊ณผ google ๊ณ์ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ณต์ ํ ๊ฒฝ์ฐ์๋ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด์ null ์ด ์๋ googleIdToken ์์ฑ์ด ์๊ณ , ์ฌ์ฉ์๊ฐ ์ ์ฅ๋ ๋น๋ฐ๋ฒํธ๋ฅผ ๊ณต์ ํ ๊ฒฝ์ฐ์๋ null ์๋ password ์์ฑ์ด ์๋ค.
์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ์ ๋ฐฑ์๋์ ์ธ์ฆํ๋ค.
๐ฅ ์ด ๋ ์๋ฒ์ ์ธ์ฆ์ ๋ณด๋ฅผ ๋ณด๋ด์ฃผ๋ ๊ฒ์ธ๊ฐ??
- ์ฌ์ฉ์ ์ด๋ฆ๊ณผ ๋น๋ฐ๋ฒํธ ์์ ๊ฐ์ ธ์จ ๊ฒฝ์ฐ ์ฌ์ฉ์๊ฐ ์๋์ผ๋ก ์ ๊ณตํ ๊ฒ๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ๋ก๊ทธ์ธํ๋ค.
- google ๊ณ์ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ผ๋ฉด ID ํ ํฐ์ ์ฌ์ฉํ์ฌ ๋ฐฑ์๋์ ์ธ์ฆํ๋ค.
// 4. ์ฌ์ฉ์ ์๋ต ์ฒ๋ฆฌ
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQ_ONE_TAP -> {
try {
val credential = oneTapClient.getSignInCredentialFromIntent(data)
val idToken = credential.googleIdToken
val username = credential.id
val password = credential.password
when {
idToken != null -> {
// Handle successful sign-in
Log.d("Google", "Got ID token: $idToken")
// You can now use this ID token for authentication or other purposes
}
password != null -> {
Log.d("Google","Got password")
}
else -> {
Log.d("Google","no id token or password")
}
}
}
}
}
}
์ํญ UI ํ์ ์ค์ง
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ ๊ฑฐ๋ถํ ๊ฒฝ์ฐ getSignInCredentialFromIntent( )๋ฅผ ํธ์ถํ๋ฉด CommonStatusCodes.CANCELDED ์ํ ์ฝ๋์ ํจ๊ป ApiException์ด ๋ฐ์ํ๋ค. ์ด ๊ฒฝ์ฐ์๋ ์ํญ ๋ก๊ทธ์ธ UI๋ฅผ ์ผ์์ ์ผ๋ก ์ฌ์ฉ ์ค์งํ์ฌ ์ฌ์ฉ์๋ค๋ก ํ์ฌ๊ธ ๋ถํธํ ๊ฐ์ ์ ๋๋ผ๊ฒ ํ์ง ์๋๋ก ํด์ผํ๋ค.
์ํญ ๋ก๊ทธ์ธ ๋ฉ์์ง์ ๋น์จ ์ ํ์ ์ง์ ๊ตฌํํ๋ ๊ฒ์ด ์ข๋ค. ์๋๋ฉด ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ๋ฉ์์ง๋ฅผ ์ฐ์์ผ๋ก ์ทจ์ํ๋ฉด ์ํฌ ํด๋ผ์ด์ธํธ๋ 24์๊ฐ ์ฟจ๋ค์ด ๊ธฐ๊ฐ์ด ๋ฐ์ํ์ฌ ์ํญ ๋ก๊ทธ์ธ UI๊ฐ ํ์๋์ง ์๋๋ค.
catch (e: ApiException) {
when (e.statusCode) {
CommonStatusCodes.CANCELED-> {
Log.d("๊ตฌ๊ธ","์ํญ ๋ค์ด์ผ๋ฌ๊ทธ was closed")
showOneTapUI = false
}
}
์ ํํ ์ด๋ค ์์ ์ ํ๋์ง ๋ก๊ทธ๋ก ํ์ธํ๊ธฐ ์ํด ์ํญ UI ์ฐฝ์ ์ฌ๋ฌ ๋ฒ ํญํ๋๋ ๊ฐ์๊ธฐ ๋ก๊ทธ์ธ ์ฐฝ์ด ๋จ์ง ์๋๋ค...!
์๋ฌ ๋ด์ฉ์ ํ์ธํด๋ณด๋ 16: Caller has been temporarily blocked due to too many canceled sign-in prompts.
๊ณต์๋ฌธ์๋ฅผ ํ์ธํด๋ณด๋ ์ฟจ๋ค์ด ๊ธฐ๊ฐ์ด ๋ฐ์ํ ๊ฒ์ด์๋ค!
์ํญ ๋ค์ด์ผ๋ก๊ทธ ์ฐฝ์ ๋ซ์ผ๋ฉด ์๋์ ๋ก๊ทธ๊ฐ ๋ฌ๋ค.
5๏ธโฃ ๋ก๊ทธ์์ ์ฒ๋ฆฌ
signOut ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋๋ค.
// 5. ๋ก๊ทธ์์ ์ฒ๋ฆฌ
binding.googleLoginOutBtn.setOnClickListener{
oneTapClient.signOut()
}
๐ฅ๋ค์ ์ด์ผ๊ธฐ
๊ณต์์์ ๊ถ์ฅํ๋ ์ธ์ฆ ๊ด๋ฆฌ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ๊ธ ๋ก๊ทธ์ธ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด๋ณด์.
๋ํ ์ํญ ๋ก๊ทธ์ธ UI ์ค google ID token์ด ์๋๋ผ password credential๋ฅผ ์ฌ์ฉํด์ ๊ตฌํํด๋ณด๋๋ก ํ๋ค.
'๐ค2024 ์๋๋ก์ด๋ > ๐ฟ ์ํ ํ๋ก์ ํธ ๊ฐ๋ฐ ์ผ์ง' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ซAndroid ๋ก๊ทธ์ธ ํ ํฐ ์ ์ฅ : Proto Datastore ์ ์ฉํ๊ธฐ (0) | 2024.03.15 |
---|---|
Android ๋คํธ์ํฌ ํต์ ๊ฐ๋ ์ตํ๊ธฐ [REST,URL, URI, Retrofit] (0) | 2024.03.05 |
[android ๋ก๊ทธ์ธ] jwt token์ผ๋ก ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์์ฑํ๊ธฐ (0) | 2024.02.15 |
[hilt 2ํ] hilt ๋ฅผ ์ฌ์ฉํ ์ข ์ ํญ๋ชฉ ์ฝ์ (0) | 2024.02.10 |
Android ์ข ์ํญ๋ชฉ ์ฝ์ ์์๋ณด๊ธฐ 1ํ (1) | 2024.02.07 |