Credential Manager适配Family Link儿童账号登录失败问题咨询
使用Credential Manager实现Firebase Google登录时适配Family Link儿童账号的问题
实现代码
suspend fun signIn(): AuthResult? { val credentialManager = CredentialManager.create(context) val googleIdOption = GetGoogleIdOption.Builder() .setServerClientId(context.getString(R.string.server_client_id)) .setFilterByAuthorizedAccounts(false) .setAutoSelectEnabled(true) .build() val request = GetCredentialRequest.Builder() .addCredentialOption(googleIdOption) .build() val result = try { val result = credentialManager.getCredential(context, request) val credential = result.credential val googleIdTokenCredential = GoogleIdTokenCredential .createFrom(credential.data) val googleIdToken = googleIdTokenCredential.idToken val firebaseCredential = GoogleAuthProvider.getCredential(googleIdToken, null) auth.signInWithCredential(firebaseCredential).await() } catch (e: Exception) { e.printStackTrace() Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show() if (e is CancellationException) throw e null } return result }
问题描述
该登录流程对普通Google账号可正常工作,但在使用由家长通过Family Link管理的儿童账号登录时,会抛出如下错误:
androidx.credentials.exceptions.NoCredentialException: No credentials available at androidx.credentials.CredentialProviderFrameworkImpl.convertToJetpackGetException$credentials_release(CredentialProviderFrameworkImpl.kt:276) at androidx.credentials.CredentialProviderFrameworkImpl$onGetCredential$outcome$2.onError(CredentialProviderFrameworkImpl.kt:152) at androidx.credentials.CredentialProviderFrameworkImpl$onGetCredential$outcome$2.onError(CredentialProviderFrameworkImpl.kt:143) at android.credentials.CredentialManager$GetCredentialTransport.lambda$onError$2(CredentialManager.java:694) at android.credentials.CredentialManager$GetCredentialTransport.$r8$lambda$nlbYav9mLBoE6Yh1vFKCvITF3ks(Unknown Source:0) at android.credentials.CredentialManager$GetCredentialTransport$$ExternalSyntheticLambda2.run(Unknown Source:6) at androidx.credentials.CredentialManager$$ExternalSyntheticLambda0.execute(D8$$SyntheticClass:0) at android.credentials.CredentialManager$GetCredentialTransport.onError(CredentialManager.java:693) at android.credentials.IGetCredentialCallback$Stub.onTransact(IGetCredentialCallback.java:123) at android.os.Binder.execTransactInternal(Binder.java:1380) at android.os.Binder.execTransact(Binder.java:1311)
当前临时解决方案
当捕获到NoCredentialException时,调用reattemptSignInUsingLegacyGoogleSignIn()函数,使用已废弃的GoogleSignIn完成用户认证,该方案可正常适配Family Link儿童账号:
fun reattemptSignInUsingLegacyGoogleSignIn(): IntentSenderRequest { val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(context.getString(R.string.server_client_id)) .requestEmail() .build(); val mGoogleSignInClient = GoogleSignIn.getClient(context, gso); val signInIntent = mGoogleSignInClient.signInIntent val pendingIntent = PendingIntent.getActivity( context, 0, signInIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) return IntentSenderRequest.Builder(pendingIntent).build() } suspend fun getSignInResultFromIntent(intent: Intent): AuthResult? { val task = GoogleSignIn.getSignedInAccountFromIntent(intent) val result = try { val account = task.getResult(ApiException::class.java) val credential = GoogleAuthProvider.getCredential(account.idToken, null) auth.signInWithCredential(credential).await() } catch (e: ApiException) { Log.w("Auth", "Google sign in failed", e); Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show() null } return result }
由于Credential Manager是GoogleSignIn的官方替代方案,理论上应支持儿童账号登录,请问需要进行哪些特定配置或修改才能让Credential Manager适配Family Link管理的儿童账号?
解决方案
1. 升级Credential Manager依赖版本
早期版本的Credential Manager对儿童账号支持不完善,需确保使用最新稳定版依赖:
implementation "androidx.credentials:credentials:1.2.2" implementation "androidx.credentials:credentials-play-services-auth:1.2.2"
2. 调整GetGoogleIdOption配置
儿童账号不支持自动选择功能,需关闭AutoSelect,强制弹出账号选择界面:
val googleIdOption = GetGoogleIdOption.Builder() .setServerClientId(context.getString(R.string.server_client_id)) .setFilterByAuthorizedAccounts(false) .setAutoSelectEnabled(false) // 关闭自动选择 .build()
3. 完善Google Cloud与Firebase配置
- 在Google Cloud Console的OAuth同意屏幕中,确保配置了符合儿童隐私要求的政策(若应用面向13岁以下用户),并启用Google Identity API。
- 验证OAuth客户端ID的包名、签名证书与应用完全匹配,儿童账号认证对客户端校验更严格。
- 在Firebase控制台中,确认Google登录提供商已启用,且关联的OAuth客户端ID与Cloud Console中的一致。
4. 优化异常处理逻辑
避免捕获泛型Exception,针对性处理NoCredentialException,并重新发起带手动选择的请求:
val result = try { val result = credentialManager.getCredential(context, request) // 原有认证逻辑 val credential = result.credential val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data) val googleIdToken = googleIdTokenCredential.idToken val firebaseCredential = GoogleAuthProvider.getCredential(googleIdToken, null) auth.signInWithCredential(firebaseCredential).await() } catch (e: NoCredentialException) { // 重新发起不带自动选择的请求 val newGoogleIdOption = GetGoogleIdOption.Builder() .setServerClientId(context.getString(R.string.server_client_id)) .setFilterByAuthorizedAccounts(false) .setAutoSelectEnabled(false) .build() val newRequest = GetCredentialRequest.Builder() .addCredentialOption(newGoogleIdOption) .build() val newResult = credentialManager.getCredential(context, newRequest) // 处理新请求结果 val credential = newResult.credential val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data) val googleIdToken = googleIdTokenCredential.idToken val firebaseCredential = GoogleAuthProvider.getCredential(googleIdToken, null) auth.signInWithCredential(firebaseCredential).await() } catch (e: CancellationException) { throw e } catch (e: Exception) { e.printStackTrace() Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show() null }
5. 确保设备系统版本支持
Credential Manager在Android 12(API 31)及以上版本正式引入,儿童账号的适配依赖系统层面支持,建议测试设备使用Android 12及以上系统。
内容的提问来源于stack exchange,提问作者user14678216
相关产品推荐
相关产品推荐

