Missing Feature{name=auth_api_credentials_begin_sign_in, version=6}

Viewed 1283

I am trying to use the Google authentication method (One tap sign in) for my application. However, after I clicked on the sign button, I faced the following problems:

W/GoogleApiManager: com.google.android.gms.internal.auth-api.zbaz could not execute call because it requires feature (auth_api_credentials_begin_sign_in, 6). D/btn click: Missing Feature{name=auth_api_credentials_begin_sign_in, version=6}.

May I know where have I messed up?

  1. I am using MsSQL instead of firebase.
  2. I have created the OAuth 2.0 client.
  3. I am using the Web Client ID for the BuildConfig (I have both Web Client and Android) buildConfigField : ("String", "CLIENT_ID", '"1113838514547 -neqok16gfh5b77v6hcg33c03d0khs896.apps.googleusercontent.com"')
  4. The google Sign in button was not working with viewBinding so I swapped to "findViewById" for that particular button

Below are the codes:

    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>

2 Answers

I was banging my head against the wall for a few days on this issue and finally Alex Mamo helped me solve it. A few things could have caused this issue. First, ensure the following:

  • User is logged in on a Google account on the emulator.
  • Both SHA-1 and SHA-256 debug fingerprints are added to the correct project.
  • The correct google-services.json file is in the correct directory.
  • The web_client_id is yours and passed correctly into the required fields.

Then if nothing changed, try running the app on a real Android device. By real I mean a device that has been used by real people for some real time and not just a demo physical device conveniently sitting right next you.

If your app still produces the same error, then there are some other issues with the app that I unfortunately cannot help with.

If your app functions correctly on a real device, then it means your emulator is not set up properly. Try spinning up a new emulator and going through the new device configuration process (for me it was called "Setting Up Your Device" and it was available as an actionable notification bar button). This is a separate/different process than simply signing into a Google Account on your Android device. Once complete, wait ten minutes and reboot for good measure. This solved my issue.

Hope this helps!

I got the same error while trying to SignIn using my Android Studio emulator. The problem was a version incompatibility with some plugins.

Broken project build gradle:

id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false

Fix:

id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false

Furthermore, download again the google-services.json file. It should solve the problem.

Edit: got again the problem and I found out that it is a problem of incompatibility between the API and the version of the emulator. Installing an emulator with API 31 (instead of 32) definitely solved the problem.

Related