我正在尝试对我的应用程序使用 Google 身份验证方法(一键登录)。但是,在我点击签名按钮后,我遇到了以下问题:
W/GoogleApiManager:com.google.android.gms.internal.auth-api.zbaz 无法执行调用,因为它需要功能(auth_api_credentials_begin_sign_in,6)。D/btn 点击:缺少功能{name=auth_api_credentials_begin_sign_in, version=6}。
我可以知道我在哪里搞砸了吗?
- 我正在使用 MsSQL 而不是 firebase。
- 我已经创建了 OAuth 2.0 客户端。
- 我正在为 BuildConfig 使用 Web 客户端 ID(我同时拥有 Web 客户端和 Android) buildConfigField : ("String", "CLIENT_ID", '"1113838514547 -neqok16gfh5b77v6hcg33c03d0khs896.apps.googleusercontent.com"')
- 谷歌登录按钮无法与 viewBinding 一起使用,因此我为该特定按钮切换到“findViewById”
以下是代码:
import android.content.IntentSender
import android.os.Bundle
import android.util.Log
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.example.myapplication.databinding.ActivitySignInBinding
import com.google.android.gms.auth.api.identity.BeginSignInRequest
import com.google.android.gms.auth.api.identity.Identity
import com.google.android.gms.auth.api.identity.SignInClient
import com.google.android.gms.common.SignInButton
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.material.snackbar.Snackbar
class MainLoginActivity : AppCompatActivity() {
private var _binding: ActivitySignInBinding? = null
private val binding get() = _binding!!
private var sign_in_button : SignInButton? = null
private var oneTapClient: SignInClient? = null
private var signUpRequest: BeginSignInRequest? = null
private var signInRequest: BeginSignInRequest? = null
private val oneTapResult = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()){ result ->
try {
val credential = oneTapClient?.getSignInCredentialFromIntent(result.data)
val idToken = credential?.googleIdToken
when {
idToken != null -> {
// Got an ID token from Google. Use it to authenticate
// with your backend.
val msg = "idToken: $idToken"
Snackbar.make(binding.root, msg, Snackbar.LENGTH_INDEFINITE).show()
Log.d("one tap", msg)
}
else -> {
// Shouldn't happen.
Log.d("one tap", "No ID token!")
Snackbar.make(binding.root, "No ID token!", Snackbar.LENGTH_INDEFINITE).show()
}
}
} catch (e: ApiException) {
when (e.statusCode) {
CommonStatusCodes.CANCELED -> {
Log.d("one tap", "One-tap dialog was closed.")
// Don't re-prompt the user.
Snackbar.make(binding.root, "One-tap dialog was closed.", Snackbar.LENGTH_INDEFINITE).show()
}
CommonStatusCodes.NETWORK_ERROR -> {
Log.d("one tap", "One-tap encountered a network error.")
// Try again or just ignore.
Snackbar.make(binding.root, "One-tap encountered a network error.", Snackbar.LENGTH_INDEFINITE).show()
}
else -> {
Log.d("one tap", "Couldn't get credential from result." +
" (${e.localizedMessage})")
Snackbar.make(binding.root, "Couldn't get credential from result.\" +\n" +
" (${e.localizedMessage})", Snackbar.LENGTH_INDEFINITE).show()
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivitySignInBinding.inflate(layoutInflater)
setContentView(binding.root)
sign_in_button = findViewById(R.id.sign_in_button)
oneTapClient = Identity.getSignInClient(this)
signUpRequest = BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
// Your server's client ID, not your Android client ID.
.setServerClientId(BuildConfig.CLIENT_ID)
// Show all accounts on the device.
.setFilterByAuthorizedAccounts(false)
.build())
.build()
signInRequest = BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
// Your server's client ID, not your Android client ID.
.setServerClientId(BuildConfig.CLIENT_ID)
// Show all accounts on the device.
.setFilterByAuthorizedAccounts(true)
.build())
.setAutoSelectEnabled(true)
.build()
sign_in_button!!.setOnClickListener{
displaySignIn()
}
}
private fun displaySignIn(){
oneTapClient?.beginSignIn(signInRequest!!)
?.addOnSuccessListener(this) { result ->
try {
val ib = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()
oneTapResult.launch(ib)
} catch (e: IntentSender.SendIntentException) {
Log.e("btn click", "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
?.addOnFailureListener(this) { e ->
// No Google Accounts found. Just continue presenting the signed-out UI.
displaySignUp()
Log.d("btn click", e.localizedMessage!!)
}
}
private fun displaySignUp() {
oneTapClient?.beginSignIn(signUpRequest!!)
?.addOnSuccessListener(this) { result ->
try {
val ib = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()
oneTapResult.launch(ib)
} catch (e: IntentSender.SendIntentException) {
Log.e("btn click", "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
?.addOnFailureListener(this) { e ->
// No Google Accounts found. Just continue presenting the signed-out UI.
displaySignUp()
Log.d("btn click", e.localizedMessage!!)
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.common.SignInButton
android:id="@+id/sign_in_button"
android:layout_width="129dp"
android:layout_height="52dp"
android:layout_marginStart="141dp"
android:layout_marginTop="252dp"
android:layout_marginEnd="141dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>