近期突然收到邮件说:您使用的是旧版 Google 登录 API,这种 API 已被弃用并计划于 2025 年移除。如需详细了解如何改而通过 Credential Manager 使用 Google 账号登录,请阅读我们的迁移指南。
然后就规划了更新但是因为别的相对紧急的需求就一直被搁置了,昨天老板突然过来说,他看到邮件说旧版Google 登录要废弃了,让我赶紧迁移,我说晚一点迁移也可以先做比较优先级高的需求,老板非常担忧说那废弃之后用户不都全登录不了怎么办!那就开始对接吧!
首先根据邮件内容来到 迁移介绍官方文档 ,看完一头雾水 不明所以,看到几个说迁移之后登录速度提升50%,而且使用更加简洁,旧版的登录回调确实不怎么优雅!
紧接着来到了重头戏 Google 登录 官方文档 仔细阅读了一下流程 并尝试编写代码:
- 依赖添加 最新版本
dependencies {
// ... other dependencies
implementation "androidx.credentials:credentials:<latest version>"
implementation "androidx.credentials:credentials-play-services-auth:<latest version>"
implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
}
- 编写登录代码
- 首先创建一个CredentialManager
credentialManager = CredentialManager
.create(context)
- 然后再构建一个 GetSignInWithGoogleOption 登录项
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder()
.setServerClientId(WEB_CLIENT_ID)
.setNonce(<nonce string to use when generating a Google ID token>)
.build()
- 触发登录操作
val request: GetCredentialRequest = GetCredentialRequest
.Builder()
.addCredentialOption(googleIdOption)
.build()
credentialManager.getCredentialAsync(
it,
request,
CancellationSignal(),
Executors.newSingleThreadExecutor(),
object : CredentialManagerCallback<GetCredentialResponse, GetCredentialException> {
override fun onError(e: GetCredentialException) {
googleCallBack?.onFailure(e)
}
override fun onResult(result: GetCredentialResponse) {
createGoogleIdToken(result.credential, googleCallBack)
}
})
- 获取登录信息 在登录成功之后会回调onResult 方法可以拿到GetCredentialResponse 此时可以通过 GoogleIdTokenCredential.createFrom 来获取用户信息
val credentialData = result.data
val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credentialData)
- 退出登录操作
val clearCredentialRequest = ClearCredentialStateRequest()
credentialManager.clearCredentialStateAsync(
clearCredentialRequest,
CancellationSignal(),
Executors.newSingleThreadExecutor(),
object : CredentialManagerCallback<Void?, ClearCredentialException> {
override fun onError(e: ClearCredentialException) {
}
override fun onResult(result: Void?) {
}
})
- 完整代码
package com.chic.point.widget.utlis
import android.content.Context
import android.os.CancellationSignal
import androidx.credentials.ClearCredentialStateRequest
import androidx.credentials.Credential
import androidx.credentials.CredentialManager
import androidx.credentials.CredentialManagerCallback
import androidx.credentials.CustomCredential
import androidx.credentials.GetCredentialRequest
import androidx.credentials.GetCredentialResponse
import androidx.credentials.exceptions.ClearCredentialException
import androidx.credentials.exceptions.GetCredentialException
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
import java.lang.ref.WeakReference
import java.util.concurrent.Executors
/**
* @date : 2025/2/26
* @author spc
* @Description:
*/
object GoogleSignInManager {
private lateinit var credentialManager: CredentialManager
private fun initCredentialManager(context: Context) {
if (::credentialManager.isInitialized.not()) {
credentialManager = CredentialManager
.create(context)
}
}
fun googleSignIn(
context: Context,
apiKey: String,
googleCallBack: GoogleCallBack? = null,
) {
val weakContext = WeakReference(context.applicationContext)
weakContext.get()?.let {
initCredentialManager(it)
val googleIdOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption
.Builder(apiKey)
.build()
val request: GetCredentialRequest = GetCredentialRequest
.Builder()
.addCredentialOption(googleIdOption)
.build()
credentialManager.getCredentialAsync(
it,
request,
CancellationSignal(),
Executors.newSingleThreadExecutor(),
object : CredentialManagerCallback<GetCredentialResponse, GetCredentialException> {
override fun onError(e: GetCredentialException) {
googleCallBack?.onFailure(e)
}
override fun onResult(result: GetCredentialResponse) {
createGoogleIdToken(result.credential, googleCallBack)
}
})
}
}
private fun createGoogleIdToken(
credential: Credential?,
googleCallBack: GoogleCallBack? = null,
) {
// Check if credential is of type Google ID
if (credential != null && credential is CustomCredential && credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
// Create Google ID Token
val credentialData = credential.data
val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credentialData)
googleCallBack?.onSuccess(googleIdTokenCredential)
} else {
googleCallBack?.onFailure(null)
}
}
/**
* to log out
*/
fun logOut(context: Context) {
val weakContext = WeakReference(context.applicationContext)
weakContext.get()?.let {
initCredentialManager(it)
val clearCredentialRequest = ClearCredentialStateRequest()
credentialManager.clearCredentialStateAsync(
clearCredentialRequest,
CancellationSignal(),
Executors.newSingleThreadExecutor(),
object : CredentialManagerCallback<Void?, ClearCredentialException> {
override fun onError(e: ClearCredentialException) {
}
override fun onResult(result: Void?) {
}
})
}
}
}