GoogleIdTokenCredential.getId()返回整数而非字符串问题求助
GoogleIdTokenCredential返回整数ID且displayName为null的异常排查与解决
我在基于GoogleIdTokenCredential构建登录系统时遇到异常:
- 部分场景下
googleIdTokenCredential.id返回整数类型值,而非官方文档承诺的非空邮箱字符串 - 同时
googleIdTokenCredential.displayName返回null
依赖配置和核心代码如下:
依赖配置(build.gradle)
dependencies { // dependencies for credential implementation("androidx.credentials:credentials-play-services-auth:1.2.2") implementation("com.google.android.libraries.identity.googleid:1.1.1") }
Fragment核心代码
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val googleIdOption by lazy { GetGoogleIdOption.Builder().setFilterByAuthorizedAccounts(false) .setServerClientId(serverClientId) .setAutoSelectEnabled(true).setNonce(generateNonce()).build() } val request: androidx.credentials.GetCredentialRequest = androidx.credentials.GetCredentialRequest.Builder().addCredentialOption(googleIdOption) .build() val mContext = requireContext() val credentialManager by lazy { androidx.credentials.CredentialManager.create(mContext) } lifecycleScope.launch { try { val result = credentialManager.getCredential( request = request, context = mContext, ) handleSignIn(result) } catch (e: androidx.credentials.exceptions.GetCredentialException) { showMessage("Failed to get credential: $e") } } } private fun handleSignIn(result: androidx.credentials.GetCredentialResponse) { when (val credential = result.credential) { is CustomCredential -> { if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) { try { val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data) val id = googleIdTokenCredential.id val displayName = googleIdTokenCredential.displayName if (displayName == null) { showMessage("Login Failed\nid: $id") return } } catch (e: GoogleIdTokenParsingException) { showMessage("Received an invalid google id token response, $e") } } } else -> { showMessage("Unexpected type of credential") } } } private fun generateNonce(): String { val nonceBytes = ByteArray(16) SecureRandom().nextBytes(nonceBytes) return Base64.encodeToString( nonceBytes, Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE ) } private fun showMessage(message: String) { Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() }
排查与解决思路
1. 显式添加必要的OAuth Scopes
官方文档中,若要获取邮箱(即id字段)和用户显示名称,需要确保请求包含email和profile scope。默认情况下GetGoogleIdOption会包含这些scope,但显式指定可以避免潜在的配置遗漏:
val googleIdOption by lazy { GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(false) .setServerClientId(serverClientId) .setAutoSelectEnabled(true) .setNonce(generateNonce()) // 显式声明需要的权限范围 .setScopes(listOf("email", "profile")) .build() }
缺失email scope是导致返回整数ID(用户的Google ID而非邮箱)的核心原因。
2. 验证Server Client ID的正确性
确保serverClientId是Google Cloud Console中创建的Web应用类型OAuth 2.0客户端ID,而非Android应用的客户端ID。错误的客户端ID会导致返回数据字段不完整。
3. 检查原始Credential数据
直接打印credential.data的完整内容,确认Google Play Services返回的原始数据是否异常:
Log.d("GoogleCredentialDebug", "Raw credential data: ${credential.data}")
如果原始数据中的id本身就是整数,说明是服务端或Play Services的返回问题,需进一步排查设备的Google Play Services版本。
4. 强制检查Google Play Services版本
设备上的Google Play Services版本过低可能导致API行为异常,添加版本检查:
val status = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(requireContext()) if (status != ConnectionResult.SUCCESS) { showMessage("请更新Google Play Services") return }
5. 调整Credential Manager初始化方式
避免使用lazy初始化credentialManager,改为在onViewCreated中直接初始化,规避生命周期相关的潜在问题:
val credentialManager = androidx.credentials.CredentialManager.create(mContext)
内容的提问来源于stack exchange,提问作者AR Sharif Uddin JUMMAN
相关产品推荐
相关产品推荐

