12

I am trying to integrate Google sign-in into my android app using Firebase, but I am running into issues. I am following the tutorial here, and I believe that I have followed it to the word. I added Firebase to my app, added my SHA-1 fingerprint, enabled Google sign-in, and added the dependencies to my grade files. Then, I copied the code in the github project linked to in the tutorial. However, when I run the application, and my code is below, I get an error when the sign-in fragment returns, and the result code is RESULT_CANCELED. This is the error output:

W/GoogleSignInActivity: Google sign in failed, resultCode: 0
                    com.google.android.gms.common.api.ApiException: 10: 
                        at com.google.android.gms.common.internal.zzb.zzy(Unknown Source:14)
                        at com.google.android.gms.auth.api.signin.GoogleSignIn.getSignedInAccountFromIntent(Unknown Source:37)
                        at com.example.root.firebasesignin.LoginActivity.onActivityResult(LoginActivity.java:63)
                        at android.app.Activity.dispatchActivityResult(Activity.java:7267)
                        at android.app.ActivityThread.deliverResults(ActivityThread.java:4524)
                        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4571)
                        at android.app.ActivityThread.-wrap19(Unknown Source:0)
                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1744)
                        at android.os.Handler.dispatchMessage(Handler.java:105)
                        at android.os.Looper.loop(Looper.java:164)
                        at android.app.ActivityThread.main(ActivityThread.java:6809)
                        at java.lang.reflect.Method.invoke(Native Method)
                        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

When I created the SHA-1 fingerprint, I did have to remake the debug keystore at ~/.android/debug.keystore using the command

keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"

and then I converted the keystore to pkcs12 using the command

keytool -importkeystore -srckeystore ~/.android/debug.keystore -destkeystore ~/.android/debug.keystore -deststoretype pkcs12

I have never used Firebase or Google sign-in for authentication, so I am very lost. I think the keystore might be the problem, and when I look in File > Project Structure > Signings nothing is shown in the left panel, and in File > Project Structure > Build Types the Signing Config box is empty. Again, I am very new to Firebase and Google authentication, so please excuse me if I'm forgetting something simple. Thank you in advance for your help.

This is the code for my main activity. The layout is simply a Google sign-in button and the action bar.

package com.example.root.firebasesignin;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GoogleAuthProvider;

public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "GoogleSignInActivity";
    private static final int RC_SIGN_IN = 9001;

    private FirebaseAuth mAuth;
    private GoogleSignInClient mGoogleSignInClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        // Button listeners
        findViewById(R.id.sign_in_button).setOnClickListener(this);

        // Configure Google Sign In
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();

        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
        mAuth = FirebaseAuth.getInstance();
    }

    @Override
    public void onStart() {
        super.onStart();
        // Check if user is signed in (non-null) and update UI accordingly.
        FirebaseUser currentUser = mAuth.getCurrentUser();
        updateUI(currentUser);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
            try {
                // Google Sign In was successful, authenticate with Firebase
                GoogleSignInAccount account = task.getResult(ApiException.class);
                firebaseAuthWithGoogle(account);
            } catch (ApiException e) {
                // Google Sign In failed, update UI appropriately
                Log.w(TAG, "Google sign in failed, resultCode: " + resultCode, e);
                updateUI(null);
            }
        }
    }

    private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
        Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());

        AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d(TAG, "signInWithCredential:success");
                            FirebaseUser user = mAuth.getCurrentUser();
                            updateUI(user);
                        } else {
                            // If sign in fails, display a message to the user.
                            Log.w(TAG, "signInWithCredential:failure", task.getException());
                            Toast.makeText(LoginActivity.this, "Authentiation failed", Toast.LENGTH_LONG).show();
                            updateUI(null);
                        }
                    }
                });
    }

    private void signIn() {
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    private void updateUI(FirebaseUser user) {
        if (user != null)
            findViewById(R.id.sign_in_button).setVisibility(View.GONE);
        else
            findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.sign_in_button)
            signIn();
    }
}
acn4
  • 121
  • 1
  • 1
  • 3

5 Answers5

4

Another reason why RESULT_CANCELED might be returned is when the activity from which you launch the authentication has android:launchMode="singleTask" configured in AndroidManifest.xml, in which case it will always get RESULT_CANCELED on its onActivityResult() method.

Changing it to android:launchMode="singleTop" fixed the issue.

Some reference: https://stackoverflow.com/a/8960126/1713163

carrizo
  • 689
  • 6
  • 15
  • I'm using singleTask launch mode, but i'm not getting this issue. – K Pradeep Kumar Reddy Dec 05 '22 at 13:05
  • This resolved my issue. When we click on "Add account" option in Google sign in dialog, the resulting callback always returned RESULT _CANCELLED. Changing activity launch mode to single_task resolved it. – Hashir Ali Jun 14 '23 at 05:30
3

com.google.android.gms.common.api.ApiException: 10 is explained by the following blockquote.

DEVELOPER ERROR The application is misconfigured. This error is not recoverable and will be treated as fatal. The developer should look at the logs after this to determine more actionable information.

This means that you could either have something wrong with your SHA-1 fingerprint or your OAuth 2.0 client ID. I doubt that there's anything wrong with your SHA-1 configuration since you followed the tutorial. The only thing left is to get your proper client ID. You first go to https://console.cloud.google.com/apis/credentials.

  1. Look for anything related to Android and is under OAuth 2.0 client IDs.
  2. Replace part of your codes with the following:

    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(webClientId)
            .requestEmail()
            .build();
    

The variable webClientId holds the Client ID you previously got from https://console.cloud.google.com/apis/credentials. Then, there you go.

Wei
  • 1,028
  • 8
  • 27
  • 2
    I found the OAuth 2.0 client ID for android, which was auto created by Google Service and replaced that value and it gave the same error. I also tried the web client auto created by Google Service which gave the same result. – acn4 Feb 28 '18 at 00:35
2
  1. Create New Project using Firebase developer Account. And Put your google-services.json within Your ProjectName/App.
  2. Then Go to the Firebase developer console --> Select your project --> Click Project Overview(Left Side)--> Select your project Settings.
  3. Go to Your app section ---> update SHA certificate fingerprints How to get debuger SHA1 Key?
  4. Go to the android studio --> Click Gradle on the right Pannel.
  5. Click on your Project Name(root). ---> click Tasks -->signing Report
  6. Click on Gradle Console in Buttom Panel.
  7. Then you got your SHA1 key.

Next: 1. Go to the Firebase developer console and select your project. 2. Click Authetication in left side panel. 3. Click SIGN IN METHOD and enable Google As true.

Mainak Devsinha
  • 169
  • 1
  • 6
2

Make sure you have the pre-requisites set up correctly :-

  1. You have added your SHA-1 debug key to your Project's configuration setting on Google or Firebase Account.
  2. Downloaded and added google-services.json to your android project after adding the debug SHA1 key in your account.
  3. Package name (on Firebase account) and Application Id (on android) must be same .. Android's package name might be different, no problems with that.

After that, simply edit the existing debug signing config in your android project's setting as mentioned here https://stackoverflow.com/a/17992232/9747826

MAKE SURE YOU IMPLEMENT BOTH THE STEPS AS MENTIONED HERE

This will setup project's default signing configuration to debug with your debug-keystore SHA1 and you are good to go!

Damanpreet Singh
  • 678
  • 10
  • 15
2

I had a similar situation using the following code:

private static final int PLAY_LOGIN = 1979;

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build();
GoogleSignInClient client = GoogleSignIn.getClient(activity, gso);
activity.startActivityForResult(client.getSignInIntent(), PLAY_LOGIN);

And trying to get the sign in result in the method:

@Override
public boolean onActivityResult(@NonNull Context context, int requestCode, int resultCode, Intent data) {
    if (requestCode == PLAY_LOGIN) {
        if (resultCode == Activity.RESULT_OK) {
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
            // process successful login data here...
        } else {
            Toast.makeText(context, "login error!", Toast.LENGTH_LONG).show();
        }

        return true;
    }
    return false;
}

Sometimes (not always reproducible) the returned code would be not Activity.RESULT_OK, but Activity.RESULT_CANCELED - even though I always acceptedthe sign in option in the Google dialog...

So my code was displaying the Toast with "login error!" and this has even caused my app not passing the Google review process.

To investigate the problem I have placed the debugger breakpoint at the line where the Toast is shown and just kept reinstalling my app and accepting the Google sign in dialog.

Then the breakpoint is sometimes hit and the Intent has the following mExtrasvalue:

Bundle[{googleSignInStatus=Status{statusCode=unknown status code: 12502, resolution=null}}]

And according to the Google doc on GoogleSignInStatusCodes the code GoogleSignInStatusCodes.SIGN_IN_CURRENTLY_IN_PROGRESS=12502 means, that another sign in is already in progress:

doc screenshot

So my answer is a heads up for anyone having this problem despite having everything configured correctly in the Firebase console.

You might want to handle this case in your code and display a different message to the user, maybe not an error, but just a warning.

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416