首次启动应用时Credential Manager调用Google登录/注册流程两次均失败,抛出NoCredentialsException
首次启动应用时Credential Manager调用Google登录/注册流程两次均失败,抛出NoCredentialsException
我最近碰到个头疼的Google登录问题,想跟大家聊聊:
用户首次从Play Store下载我的应用后,尝试通过Google登录时,不管是走「已有应用账号」的登录流程,还是「新用户注册」流程,都会直接抛出NoCredentialsException失败。但神奇的是,有时候只要做一些无关操作,比如重启应用(杀死进程再打开,不过也不是次次生效)、旋转设备,甚至只是在引导页随便点个按钮、切到桌面再切回应用,登录功能就突然正常了——而且这些操作也不是每次都能触发成功,完全没规律。
我已经试过好几种方案了,但都没解决问题:
- 最开始我是用Activity上下文初始化的CredentialManager,后来换成通过Koin注入Application上下文,想着可能是UI上下文的生命周期问题,但没用;
- 把
GetGoogleIdOption换成GetSignInWithGoogleOption,依然没效果; - 偶然发现有时候在引导页点击某个元素后再发起登录请求,居然能成功,但这完全不是可依赖的解决方案。
我还注意到Google的Issue Tracker上有类似的未修复问题,但显然官方还没跟进。
下面是我当前的GoogleAuthClient实现代码:
actual class GoogleAuthClient( private val activityProvider: ActivityProvider, private val manager: CredentialManager ) { actual suspend fun getIdToken(clientId: String): String? { val activity = activityProvider.currentActivity() ?: return null val signIn = GetGoogleIdOption.Builder() .setServerClientId(clientId) .setFilterByAuthorizedAccounts(true) .setAutoSelectEnabled(true) .build() val signUp = GetGoogleIdOption.Builder() .setServerClientId(clientId) .setFilterByAuthorizedAccounts(false) .setAutoSelectEnabled(false) .build() val trySignIn = GetCredentialRequest.Builder().addCredentialOption(signIn).build() val trySignUp = GetCredentialRequest.Builder().addCredentialOption(signUp).build() val response = try { manager.getCredential(activity, trySignIn) } catch (e: NoCredentialException) { CrashReporter.recordException(e) try { manager.getCredential(activity, trySignUp) } catch (e: NoCredentialException) { CrashReporter.log("No credentials found for the second time") CrashReporter.recordException(e) return null } } catch (e: CancellationException) { throw e } catch (e: Exception) { CrashReporter.recordException(e) return null } return handleSignIn(response.credential) } private fun handleSignIn(credential: Credential): String? { if (credential is CustomCredential && credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) { return try { GoogleIdTokenCredential.createFrom(credential.data).idToken } catch (e: GoogleIdTokenParsingException) { CrashReporter.recordException(e); null } } return null } actual suspend fun signOut() { try { manager.clearCredentialState(ClearCredentialStateRequest()) } catch (e: CancellationException) { throw e } catch (e: Exception) { CrashReporter.recordException(e) } } }
有没有朋友遇到过类似的情况?或者有什么我没考虑到的排查方向吗?
内容来源于stack exchange
相关产品推荐
相关产品推荐

