Chr*_*hua 24 kotlin google-signin google-one-tap
我正在尝试对我的应用程序使用 Google 身份验证方法(一键登录)。然而,当我点击签名按钮后,我遇到了以下问题:
\nW/GoogleApiManager:com.google.android.gms.internal.auth-api.zbaz 无法执行调用,因为它需要功能(auth_api_credentials_begin_sign_in,6)。\nD/btn\xc2\xa0click:缺少功能{name=auth_api_credentials_begin_sign_in,版本=6}。
\n我可以知道我哪里搞砸了吗?
\n下面是代码:
\n import android.content.IntentSender\nimport android.os.Bundle\nimport android.util.Log\nimport androidx.activity.result.IntentSenderRequest\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.appcompat.app.AppCompatActivity\nimport com.example.myapplication.databinding.ActivitySignInBinding\nimport com.google.android.gms.auth.api.identity.BeginSignInRequest\nimport com.google.android.gms.auth.api.identity.Identity\nimport com.google.android.gms.auth.api.identity.SignInClient\nimport com.google.android.gms.common.SignInButton\nimport com.google.android.gms.common.api.ApiException\nimport com.google.android.gms.common.api.CommonStatusCodes\nimport com.google.android.material.snackbar.Snackbar\n\n\nclass MainLoginActivity : AppCompatActivity() {\n\n private var _binding: ActivitySignInBinding? = null\n private val binding get() = _binding!!\n\n private var sign_in_button : SignInButton? = null\n\n private var oneTapClient: SignInClient? = null\n private var signUpRequest: BeginSignInRequest? = null\n private var signInRequest: BeginSignInRequest? = null\n\n private val oneTapResult = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()){ result ->\n try {\n val credential = oneTapClient?.getSignInCredentialFromIntent(result.data)\n val idToken = credential?.googleIdToken\n when {\n idToken != null -> {\n // Got an ID token from Google. Use it to authenticate\n // with your backend.\n val msg = "idToken: $idToken"\n Snackbar.make(binding.root, msg, Snackbar.LENGTH_INDEFINITE).show()\n Log.d("one tap", msg)\n }\n else -> {\n // Shouldn\'t happen.\n Log.d("one tap", "No ID token!")\n Snackbar.make(binding.root, "No ID token!", Snackbar.LENGTH_INDEFINITE).show()\n }\n }\n } catch (e: ApiException) {\n when (e.statusCode) {\n CommonStatusCodes.CANCELED -> {\n Log.d("one tap", "One-tap dialog was closed.")\n // Don\'t re-prompt the user.\n Snackbar.make(binding.root, "One-tap dialog was closed.", Snackbar.LENGTH_INDEFINITE).show()\n }\n CommonStatusCodes.NETWORK_ERROR -> {\n Log.d("one tap", "One-tap encountered a network error.")\n // Try again or just ignore.\n Snackbar.make(binding.root, "One-tap encountered a network error.", Snackbar.LENGTH_INDEFINITE).show()\n }\n else -> {\n Log.d("one tap", "Couldn\'t get credential from result." +\n " (${e.localizedMessage})")\n Snackbar.make(binding.root, "Couldn\'t get credential from result.\\" +\\n" +\n " (${e.localizedMessage})", Snackbar.LENGTH_INDEFINITE).show()\n }\n }\n }\n }\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n _binding = ActivitySignInBinding.inflate(layoutInflater)\n setContentView(binding.root)\n\n sign_in_button = findViewById(R.id.sign_in_button)\n\n oneTapClient = Identity.getSignInClient(this)\n signUpRequest = BeginSignInRequest.builder()\n .setGoogleIdTokenRequestOptions(\n BeginSignInRequest.GoogleIdTokenRequestOptions.builder()\n .setSupported(true)\n // Your server\'s client ID, not your Android client ID.\n .setServerClientId(BuildConfig.CLIENT_ID)\n // Show all accounts on the device.\n .setFilterByAuthorizedAccounts(false)\n .build())\n .build()\n signInRequest = BeginSignInRequest.builder()\n .setGoogleIdTokenRequestOptions(\n BeginSignInRequest.GoogleIdTokenRequestOptions.builder()\n .setSupported(true)\n // Your server\'s client ID, not your Android client ID.\n .setServerClientId(BuildConfig.CLIENT_ID)\n // Show all accounts on the device.\n .setFilterByAuthorizedAccounts(true)\n .build())\n .setAutoSelectEnabled(true)\n .build()\n\n\n sign_in_button!!.setOnClickListener{\n displaySignIn()\n }\n\n\n }\n\n\n private fun displaySignIn(){\n oneTapClient?.beginSignIn(signInRequest!!)\n ?.addOnSuccessListener(this) { result ->\n try {\n val ib = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()\n oneTapResult.launch(ib)\n } catch (e: IntentSender.SendIntentException) {\n Log.e("btn click", "Couldn\'t start One Tap UI: ${e.localizedMessage}")\n }\n }\n ?.addOnFailureListener(this) { e ->\n // No Google Accounts found. Just continue presenting the signed-out UI.\n displaySignUp()\n Log.d("btn click", e.localizedMessage!!)\n }\n }\n\n private fun displaySignUp() {\n oneTapClient?.beginSignIn(signUpRequest!!)\n ?.addOnSuccessListener(this) { result ->\n try {\n val ib = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()\n oneTapResult.launch(ib)\n } catch (e: IntentSender.SendIntentException) {\n Log.e("btn click", "Couldn\'t start One Tap UI: ${e.localizedMessage}")\n }\n }\n ?.addOnFailureListener(this) { e ->\n // No Google Accounts found. Just continue presenting the signed-out UI.\n displaySignUp()\n Log.d("btn click", e.localizedMessage!!)\n }\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n import android.content.IntentSender\nimport android.os.Bundle\nimport android.util.Log\nimport androidx.activity.result.IntentSenderRequest\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.appcompat.app.AppCompatActivity\nimport com.example.myapplication.databinding.ActivitySignInBinding\nimport com.google.android.gms.auth.api.identity.BeginSignInRequest\nimport com.google.android.gms.auth.api.identity.Identity\nimport com.google.android.gms.auth.api.identity.SignInClient\nimport com.google.android.gms.common.SignInButton\nimport com.google.android.gms.common.api.ApiException\nimport com.google.android.gms.common.api.CommonStatusCodes\nimport com.google.android.material.snackbar.Snackbar\n\n\nclass MainLoginActivity : AppCompatActivity() {\n\n private var _binding: ActivitySignInBinding? = null\n private val binding get() = _binding!!\n\n private var sign_in_button : SignInButton? = null\n\n private var oneTapClient: SignInClient? = null\n private var signUpRequest: BeginSignInRequest? = null\n private var signInRequest: BeginSignInRequest? = null\n\n private val oneTapResult = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()){ result ->\n try {\n val credential = oneTapClient?.getSignInCredentialFromIntent(result.data)\n val idToken = credential?.googleIdToken\n when {\n idToken != null -> {\n // Got an ID token from Google. Use it to authenticate\n // with your backend.\n val msg = "idToken: $idToken"\n Snackbar.make(binding.root, msg, Snackbar.LENGTH_INDEFINITE).show()\n Log.d("one tap", msg)\n }\n else -> {\n // Shouldn\'t happen.\n Log.d("one tap", "No ID token!")\n Snackbar.make(binding.root, "No ID token!", Snackbar.LENGTH_INDEFINITE).show()\n }\n }\n } catch (e: ApiException) {\n when (e.statusCode) {\n CommonStatusCodes.CANCELED -> {\n Log.d("one tap", "One-tap dialog was closed.")\n // Don\'t re-prompt the user.\n Snackbar.make(binding.root, "One-tap dialog was closed.", Snackbar.LENGTH_INDEFINITE).show()\n }\n CommonStatusCodes.NETWORK_ERROR -> {\n Log.d("one tap", "One-tap encountered a network error.")\n // Try again or just ignore.\n Snackbar.make(binding.root, "One-tap encountered a network error.", Snackbar.LENGTH_INDEFINITE).show()\n }\n else -> {\n Log.d("one tap", "Couldn\'t get credential from result." +\n " (${e.localizedMessage})")\n Snackbar.make(binding.root, "Couldn\'t get credential from result.\\" +\\n" +\n " (${e.localizedMessage})", Snackbar.LENGTH_INDEFINITE).show()\n }\n }\n }\n }\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n _binding = ActivitySignInBinding.inflate(layoutInflater)\n setContentView(binding.root)\n\n sign_in_button = findViewById(R.id.sign_in_button)\n\n oneTapClient = Identity.getSignInClient(this)\n signUpRequest = BeginSignInRequest.builder()\n .setGoogleIdTokenRequestOptions(\n BeginSignInRequest.GoogleIdTokenRequestOptions.builder()\n .setSupported(true)\n // Your server\'s client ID, not your Android client ID.\n .setServerClientId(BuildConfig.CLIENT_ID)\n // Show all accounts on the device.\n .setFilterByAuthorizedAccounts(false)\n .build())\n .build()\n signInRequest = BeginSignInRequest.builder()\n .setGoogleIdTokenRequestOptions(\n BeginSignInRequest.GoogleIdTokenRequestOptions.builder()\n .setSupported(true)\n // Your server\'s client ID, not your Android client ID.\n .setServerClientId(BuildConfig.CLIENT_ID)\n // Show all accounts on the device.\n .setFilterByAuthorizedAccounts(true)\n .build())\n .setAutoSelectEnabled(true)\n .build()\n\n\n sign_in_button!!.setOnClickListener{\n displaySignIn()\n }\n\n\n }\n\n\n private fun displaySignIn(){\n oneTapClient?.beginSignIn(signInRequest!!)\n ?.addOnSuccessListener(this) { result ->\n try {\n val ib = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()\n oneTapResult.launch(ib)\n } catch (e: IntentSender.SendIntentException) {\n Log.e("btn click", "Couldn\'t start One Tap UI: ${e.localizedMessage}")\n }\n }\n ?.addOnFailureListener(this) { e ->\n // No Google Accounts found. Just continue presenting the signed-out UI.\n displaySignUp()\n Log.d("btn click", e.localizedMessage!!)\n }\n }\n\n private fun displaySignUp() {\n oneTapClient?.beginSignIn(signUpRequest!!)\n ?.addOnSuccessListener(this) { result ->\n try {\n val ib = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()\n oneTapResult.launch(ib)\n } catch (e: IntentSender.SendIntentException) {\n Log.e("btn click", "Couldn\'t start One Tap UI: ${e.localizedMessage}")\n }\n }\n ?.addOnFailureListener(this) { e ->\n // No Google Accounts found. Just continue presenting the signed-out UI.\n displaySignUp()\n Log.d("btn click", e.localizedMessage!!)\n }\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\r\n小智 8
我在这个问题上折腾了好几天,最后Alex Mamo帮我解决了。有几件事可能导致此问题。首先,确保以下几点:
然后,如果没有任何变化,请尝试在真实的 Android 设备上运行该应用程序。我所说的“真实”是指已经被真人实时使用过的设备,而不仅仅是方便地坐在您旁边的演示物理设备。
如果您的应用程序仍然产生相同的错误,则说明该应用程序还存在其他一些问题,遗憾的是我无法提供帮助。
如果您的应用程序在真实设备上正常运行,则意味着您的模拟器设置不正确。尝试启动一个新的模拟器并完成新的设备配置过程(对我来说,它被称为“设置您的设备”,它作为可操作的通知栏按钮提供)。与简单地在 Android 设备上登录 Google 帐户相比,这是一个单独/不同的过程。完成后,等待十分钟并重新启动以获得良好的效果。这解决了我的问题。
希望这可以帮助!
小智 0
我在尝试使用 Android Studio 模拟器登录时遇到了同样的错误。问题是与某些插件的版本不兼容。
损坏的项目构建 gradle:
id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false
Run Code Online (Sandbox Code Playgroud)
使固定:
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
Run Code Online (Sandbox Code Playgroud)
此外,再次下载该google-services.json文件。它应该可以解决问题。
编辑:再次遇到这个问题,我发现这是API和模拟器版本不兼容的问题。安装具有 API 31(而不是 32)的模拟器肯定可以解决问题。