You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google One Tap登录addOnSuccessListener不触发,空引用错误求助

Google One Tap Sign In 回调不触发问题排查

问题现象

代码可正常运行,按钮可点击,但addOnSuccessListener始终不执行,仅能获取到监听器失败时的空引用错误。已按官方文档完成配置,排查过常见方案仍未解决,怀疑是Google Play Console或Firebase配置问题,但无法确定。

相关代码

MainActivity.kt

// Tags
private val TAG_SIGNIN = "Google Sign In"
private val TAG_FIREBASE = "Firebase backend auth"
private val TAG_GOOGLE = "Google Sign In Results"

@AndroidEntryPoint
class MainActivity2 : ComponentActivity() {

    // Google Sign in
    private lateinit var oneTapClient: SignInClient
    private lateinit var signInRequest: BeginSignInRequest
    private lateinit var signUpRequest: BeginSignInRequest

    // Firebase
    private lateinit var auth: FirebaseAuth

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Firebase Auth Instantiate
        auth = Firebase.auth

        // Google Onetap Sign in
        oneTapClient = Identity.getSignInClient(this)
        signInRequest = BeginSignInRequest.builder()
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    .setServerClientId(getString(R.string.firebase_client_id))
                    .setFilterByAuthorizedAccounts(true)
                    .build())
            .setAutoSelectEnabled(true)
            .build()
        signUpRequest = BeginSignInRequest.builder()
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    .setServerClientId(getString(R.string.firebase_client_id))
                    .setFilterByAuthorizedAccounts(false)
                    .build())
            .build()

        setContent {
         
            val authViewModel: LoginViewModel = viewModel()
            val authState = authViewModel.viewstate.collectAsState().value

            LoginScreen(
                activity,
                oneTapClient,
                signInRequest,
                signUpRequest,
                authViewModel,
                auth)
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LoginScreen(
    activity: Activity,
    oneTapClient: SignInClient,
    signInRequest: BeginSignInRequest,
    signUpRequest: BeginSignInRequest,
    loginViewModel: LoginViewModel,
    auth: FirebaseAuth,
) {

    val launcher = rememberLauncherForActivityResult(
        ActivityResultContracts.StartIntentSenderForResult()
    ) { result ->
        if (result.resultCode == RESULT_OK) {
            val credential = oneTapClient.getSignInCredentialFromIntent(result.Data)
            val idToken = credential.googleIdToken

            if (idToken != null) {
                // Got an ID token from Google. Use it to authenticate
                // with your backend.

                when {
                    idToken != null -> {
                        // Got an ID token from Google. Use it to authenticate
                        // with Firebase.
                        val firebaseCredential = getCredential(idToken, null)
                        auth.signInWithCredential(firebaseCredential)
                            .addOnCompleteListener(activity) { task ->
                                if (task.isSuccessful) {
                                    // Sign in success, update UI with the signed-in user's information
                                    Log.d(TAG_FIREBASE, "signInWithCredential:success")
                                    val user = auth.currentUser
                                } else {
                                    // If sign in fails, display a message to the user.
                                    Log.w(TAG_FIREBASE,
                                        "signInWithCredential:failure",
                                        task. Exception)
                                }
                            }
                    }
                    else -> {
                        // Shouldn't happen.
                        Log.d(TAG_GOOGLE, "No ID token!")
                    }
                }
                Log.d("LOG", idToken)
            } else {
                Log.d("LOG", "Null Token")
            }
        } else {
            Log.e("Response", "${result.resultCode}")
        }
    }

    Material3AppTheme() {
        Scaffold { padding ->
            padding
            Column(
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                val scope = rememberCoroutineScope()
                Surface(
                    onClick = {
                        scope.launch {
                            loginViewModel.signIn(activity, oneTapClient, signInRequest, signUpRequest, launcher)
                        }
                    },
                    color = MaterialTheme.colorScheme.onPrimary,
                    shadowElevation = 0.dp,
                    shape = RoundedCornerShape(5.dp),
                    border = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.primaryContainer),
                ) {
                    Row(
                        modifier = Modifier
                            .padding(
                                start = 12.dp,
                                end = 16.dp,
                            ),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.Center,
                    ) {

                        Icon(
                            painter = painterResource(id = R.drawable.ic_google_logo),
                            contentDescription = "SignInButton",
                            tint = androidx.compose.ui.graphics.Color.Unspecified,
                        )

                        Text(text = "Sign in with Google")
                    }
                }
            }
        }
    }
}

LoginViewModel.kt

fun signIn(
        activity: Activity,
        oneTapClient: SignInClient,
        signInRequest: BeginSignInRequest,
        signUpRequest: BeginSignInRequest,
        launcher: ActivityResultLauncher<IntentSenderRequest>,
    ) {
        oneTapClient.beginSignIn(signInRequest)
            .addOnSuccessListener(activity) { result ->
                try {
                    val intentSenderRequest = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()
                    launcher.launch(intentSenderRequest)
                    Log.d(TAG_SIGNIN, "Started One Tap Sign In")
                } catch (e: IntentSender.SendIntentException) {
                    Log.e(TAG_SIGNIN, "Couldn't start One Tap UI: ${e.localizedMessage}")
                }
            }
            .addOnFailureListener(activity) { e ->
                e.localizedMessage?.let { Log.d(TAG_SIGNUP, "$it: non functional") }

                oneTapClient.beginSignIn(signUpRequest)
                    .addOnSuccessListener(activity) { result ->
                        try {
                            val intentSenderRequest = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()
                            launcher.launch(intentSenderRequest)
                        } catch (e: IntentSender.SendIntentException) {
                            Log.e(TAG_SIGNUP, "Couldn't start One Tap UI: ${e.localizedMessage}")
                        }
                    }
                    .addOnFailureListener(activity) { e ->
                        // No Google Accounts found. Just continue presenting the signed-out UI.
                        e.localizedMessage?.let { Log.d(TAG_SIGNUP, "$it: even less non functional") }
                    }
            }
    }

排查与修复方案

  1. 代码细节修正

    • 回调中result.Data应为result.data(小写d),这是导致空指针的直接原因,修正后可正常获取凭证:
      val credential = oneTapClient.getSignInCredentialFromIntent(result.data)
      
    • 检查viewModel中TAG_SIGNIN、TAG_SIGNUP是否已正确定义,避免日志缺失。
  2. 配置信息校验

    • 确认Firebase控制台的Web类型OAuth 2.0 客户端ID已正确填入strings.xml的firebase_client_id字段。
    • 检查Google Play Console中应用的SHA-1和SHA-256指纹,已同步到Firebase项目设置(两种指纹都需添加)。
    • 确认Firebase控制台Authentication模块已启用Google登录提供商。
  3. 设备与环境检查

    • 测试设备需登录有效Google账号,且Google Play服务为最新版本。
    • 优先使用真机测试,部分模拟器的Google服务存在兼容性问题。
    • 清除应用缓存后重新测试,避免旧配置残留。
  4. 权限与签名验证

    • 应用签名配置(debug/release)需与Firebase中添加的指纹完全匹配,debug包用debug指纹,release包用release指纹。
    • 确保AndroidManifest.xml添加了必要权限:
      <uses-permission android:name="android.permission.INTERNET" />
      

内容的提问来源于stack exchange,提问作者ibbs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:15:39