Firebase SignInClient遇ApiException:8及模拟器功能缺失问题求助
Google一键登录异常:ApiException:8 与 Missing Feature 错误排查
问题现象
点击谷歌邮箱授权图标按钮时出现以下异常:
- OnePlus 7T真机:抛出
ApiException:8 - 模拟器:提示
Missing Feature{name=auth_api_credentials_begin_sign_in, version=8}
已尝试的无效方案
- 清理应用缓存
- 重新放置
google-services.json文件到应用包内 - 修正SHA1和SHA256签名值为正确值
- 确认真机谷歌服务已授权
- 验证Web Client ID正确无误
- 梳理并优化代码逻辑
- 新建项目导入现有代码重试
相关代码
ViewModel依赖注入字段
@GmailSignIn private val signIn: BeginSignInRequest, @GmailSignUp private val signUp: BeginSignInRequest // 注:上述变量来自ViewModel构造函数,用于处理授权逻辑:已有授权账号则登录,否则注册
Hilt提供的请求实例
@Provides @GmailSignIn fun provideSignInRequest() = BeginSignInRequest.builder() .setGoogleIdTokenRequestOptions( BeginSignInRequest.GoogleIdTokenRequestOptions.builder() .setSupported(true) .setServerClientId(ServerClient) .setFilterByAuthorizedAccounts(true) .build() ) .setAutoSelectEnabled(true) .build() @Provides @GmailSignUp fun provideSignUpRequest() = BeginSignInRequest.builder() .setGoogleIdTokenRequestOptions( BeginSignInRequest.GoogleIdTokenRequestOptions.builder() .setSupported(true) .setServerClientId(ServerClient) .setFilterByAuthorizedAccounts(false) .build() ) .build() // 注:使用Hilt实现注解的依赖注入
自定义Qualifier注解
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class GmailSignIn @Qualifier @Retention(AnnotationRetention.BINARY) annotation class GmailSignUp
ViewModel中的登录与授权逻辑
// 注:该函数用于向其他页面传递Gmail登录数据 suspend fun gmailOneTapClient(): IntentSender { val signInResult = oneTapClient.beginSignIn(signIn).await() stateAuthWithGmail.emit( AuthSignInResult( successful = oneTapClient.beginSignIn(signIn).await(), errorMessage = null, Loading = false ) ) if(signInResult == null){ oneTapClient.beginSignIn(signUp).await() stateAuthWithGmail.emit( AuthSignInResult( successful = oneTapClient.beginSignIn(signUp).await(), errorMessage = null, Loading = false ) ) } return signInResult.pendingIntent.intentSender } // 注:该函数处理Gmail授权逻辑 fun gmailAuth(credential: AuthCredential){ viewModelScope.launch(Dispatchers.IO){ stateAuthWithGmail.emit( AuthSignInResult( errorMessage = null, Loading = true ) ) when(val result = authorizationRepository.gmailAuth(credential)){ is GmailAuthorizationEvent.Error ->{ stateAuthWithGmail.emit( AuthSignInResult( errorMessage = result.errorMessage, successful = null ) ) } is GmailAuthorizationEvent.Success ->{ stateAuthWithGmail.emit( AuthSignInResult( errorMessage = null, Loading = false, successful = result.data ) ) } is GmailAuthorizationEvent.Loading ->{ stateAuthWithGmail.emit( AuthSignInResult( errorMessage = null, successful = null, Loading = true ) ) } } } }
登录结果处理Launcher
// 注:该Launcher用于在其他页面获取IntentSender数据,导航组件配置无误 val launcherGmailSignIn = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartIntentSenderForResult() ){ activityResult -> if(activityResult.resultCode == Activity.RESULT_OK){ try { val credentials = oneTapClient.getSignInCredentialFromIntent( activityResult.data ) val googleIdToken = credentials.googleIdToken val googleCred = GoogleAuthProvider.getCredential(googleIdToken,null) authorizationViewModel.gmailAuth(googleCred) }catch (e:ApiException){ print(e) } } }
登录触发与导航逻辑
// 注:该逻辑用于跳转并获取用户数据到其他页面 navigateToGoogleSignIn = { navigationScope.launch(Dispatchers.Main){ launcherGmailSignIn.launch( IntentSenderRequest.Builder( authorizationViewModel.gmailOneTapClient() ).build() ) navController.navigate("news_screen") } }
排查与解决建议
1. 升级Google Play服务版本
Missing Feature错误核心原因是设备/模拟器的Google Play服务版本过低,不支持BeginSignInRequest要求的API版本(version=8):
- 真机:打开Google Play商店,搜索「Google Play服务」并更新到最新版本
- 模拟器:创建AVD时选择Android 12及以上的系统镜像(确保包含Google Play服务),或在模拟器内手动更新Google Play服务
2. 修复gmailOneTapClient的逻辑问题
原代码存在重复调用beginSignIn、空值处理错误的问题,会导致重复请求触发限制,修改如下:
suspend fun gmailOneTapClient(): IntentSender { val signInResult = try { // 先尝试登录已有授权账号 oneTapClient.beginSignIn(signIn).await() } catch (e: ApiException) { // 登录失败(无授权账号),切换到注册流程 oneTapClient.beginSignIn(signUp).await() } // 仅发送一次正确的状态 stateAuthWithGmail.emit( AuthSignInResult( successful = signInResult, errorMessage = null, Loading = false ) ) return signInResult.pendingIntent.intentSender }
3. 验证OAuth客户端配置
- 登录Google Cloud控制台,确认Android客户端和Web客户端的SHA1/SHA256签名均已正确配置(与本地签名文件一致)
- 检查
ServerClient是否为Web客户端的Client ID,而非Android客户端ID - 确保OAuth同意屏幕已完成配置,测试阶段需添加测试用户邮箱
4. 处理ApiException:8的场景
ApiException:8对应CommonStatusCodes.INTERNAL_ERROR,常见解决方向:
- 确保设备网络正常,可访问Google服务
- 避免在非主线程处理UI相关的登录请求(协程调度器使用
Dispatchers.Main或合适的调度器) - 清理设备上已保存的Google账号授权记录,重新授权
5. 优化导航逻辑
原代码在启动登录流程后立即跳转页面,会导致登录结果无法正确接收,需改为登录成功后再导航:
// 在ViewModel的gmailAuth函数中,成功分支添加导航逻辑 is GmailAuthorizationEvent.Success -> { stateAuthWithGmail.emit( AuthSignInResult( errorMessage = null, Loading = false, successful = result.data ) ) // 触发导航事件,让UI层处理跳转 _navigateToNewsScreen.emit(Unit) } // UI层监听导航事件 LaunchedEffect(authorizationViewModel.navigateToNewsScreen) { authorizationViewModel.navigateToNewsScreen.collect { navController.navigate("news_screen") } } // 修改登录触发逻辑,移除立即跳转 navigateToGoogleSignIn = { navigationScope.launch(Dispatchers.Main) { launcherGmailSignIn.launch( IntentSenderRequest.Builder( authorizationViewModel.gmailOneTapClient() ).build() ) } }
内容的提问来源于stack exchange,提问作者zadgee
相关产品推荐
相关产品推荐

