4

Whenever I try to sign in by launching the google sign-in intent, it directly goes to the onActivityResult without me having the chance to choose an account. All It does is dimm the screen, but the window to select an account doesn't show up. The Login then fails with this ApiException:

java.lang.ClassNotFoundException: com.google.android.gms.common.api.Scope

and

java.lang.RuntimeException: Canvas: trying to draw too large(256000000bytes) bitmap.

(full stack trace: https://pastebin.com/vBZeBLu0)

All of my used dependencies are up to date and my credentials (oAuth client-id) are all set up correctly, I tried the solutions of other similar problems, but none of them solved my issue, i also checked if the user is logged out completely from the device and the issue kept reaccuring.

This is my Log-in Activity:

public class Login extends Activity implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks  {                                   

private static final String TAG = "LoginProcess";

SignInButton gsignInButton;
private static final int RC_SIGN_IN = 1;
DatabaseReference mRef;
FirebaseAuth mAuth;
FirebaseAuth.AuthStateListener mAuthListener;
GoogleSignInOptions gso;
GoogleApiClient mGoogleApiClient;


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

    mAuth = FirebaseAuth.getInstance();



    gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .build();

    mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

    gsignInButton = findViewById(R.id.sib);

    gsignInButton.setColorScheme(SignInButton.COLOR_DARK); // wide button style
    gsignInButton.setOnClickListener(myhandler);


}

View.OnClickListener myhandler = new View.OnClickListener() {
    public void onClick(View v) {
       signIn();
    }

};



public void signIn() {

    Intent signInIntent = mGoogleSignInClient.getSignInIntent();
    startActivityForResult(signInIntent, RC_SIGN_IN);
}

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

    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", e);  //this is where it always lands.
            Toast.makeText(this, "login failed", Toast.LENGTH_SHORT).show();
            // ...
        }
    }

}

full code for Login Activity: https://pastebin.com/6Yi7vzD7

Gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    buildToolsVersion '28.0.3'

    defaultConfig {
        applicationId "com.example.sanchez.worldgramproject"
        minSdkVersion 21
        targetSdkVersion 28
        multiDexEnabled true
        versionCode 0
        versionName "0"


    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            debuggable true
        }
    }
}



dependencies {

    compile fileTree(dir: 'libs', include: ['*.jar'])
    api "com.google.android.material:material:1.0.0"

    implementation 'com.github.madrapps:pikolo:1.1.6'
    implementation 'com.google.android.gms:play-services-drive:16.0.0'
    implementation 'com.google.android.material:material:1.1.0-alpha02'
    implementation 'com.github.bumptech.glide:glide:3.8.0'
    implementation'com.firebaseui:firebase-ui-storage:2.3.0'
    implementation 'com.google.firebase:firebase-auth:16.1.0'
    implementation 'com.google.android.gms:play-services-auth:16.0.1'
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'com.jakewharton:butterknife:8.8.1'
    implementation 'androidx.multidex:multidex:2.0.1'
    implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.6'
    implementation 'de.hdodenhof:circleimageview:2.2.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.exifinterface:exifinterface:1.0.0'
    implementation 'com.google.firebase:firebase-storage:16.0.5'
    implementation 'com.google.android.gms:play-services-maps:16.0.0'
    implementation 'com.google.firebase:firebase-database:16.0.5'
    testImplementation 'junit:junit:4.12'

}


apply plugin: 'com.google.gms.google-services'

I have no idea what the cause of the problem is, how can i solve this issue and make the account selection window pop up?

EDIT 2.1.2019

Instead of the above ApiExeption i get this error:

W/LoginProcess: Google sign in failed
    com.google.android.gms.common.api.ApiException: 8: 
        at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(Unknown Source:4)
        at com.google.android.gms.auth.api.signin.GoogleSignIn.getSignedInAccountFromIntent(Unknown Source:8)
        at com.example.sanchez.worldgramproject.Login.onActivityResult(Login.java:162)
        at android.app.Activity.dispatchActivityResult(Activity.java:7548)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4485)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4532)
        at android.app.ActivityThread.-wrap20(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1752)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6938)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

I believe something went wrong with how i set up my oAuth (Auto generated by Firebase)

Ale4303
  • 429
  • 3
  • 10
  • 29
  • Possible duplicate of [Android Google Drive implementation : getting the exception "java.lang.ClassNotFoundException: com.google.android.gms.common.api.Scope"](https://stackoverflow.com/questions/43500747/android-google-drive-implementation-getting-the-exception-java-lang-classnotf) – Martin Zeitler Dec 28 '18 at 22:47
  • I tried everything on that thread and it didn't work – Ale4303 Dec 29 '18 at 00:21
  • this sounds unlikely, because it obviously is a `multidex` issue. – Martin Zeitler Dec 29 '18 at 00:32
  • I have added the multidex enabled before the problem was occuring, maybe it has to do with the androidx compatibility (i have added the full gradle file in my new edit) – Ale4303 Dec 29 '18 at 00:58
  • did you try it on different emulator or device? – Rizwan Atta Dec 31 '18 at 02:23
  • yes I've tried it on an Nexus 5X with Api 28 and because it didn't have a google account on the device already, instead of going to the popup window it went to the "create google account" window. After creating a new google account it was saved on the device, yet the "choose account window" still didn't pop up after loggin out of the first account and wanting to choose another one – Ale4303 Dec 31 '18 at 16:12
  • What about **Canvas: trying to draw too large(256000000bytes) bitmap.**? I guess the launcher icon that you've used, which also appears in the account chooser dialog, is stopping the dialog from popping. Just guessing. – Niraj Niroula Jan 02 '19 at 04:22
  • 2
    Niraj Niroula, it actually worked! can you post it as an answer so i can give you the points? also, is there still a way to use my old image (that is too big) but have it in different sizes so i could use it for the login? – Ale4303 Jan 02 '19 at 13:19
  • Move your image in the (hi-res) drawable to drawable-xxhdpi. But in app development, you do not need to use large image. It will increase your APK file size. – Viral Patel Jan 04 '19 at 12:16
  • @Ale4303 I suggest you to compress the image file using any image editing software (Photoshop, GIMP, e.t.c.). The account chooser dialog doesn't need hi-res images. Take a look at [this](https://stackoverflow.com/questions/12768128/android-launcher-icon-size), scale the launcher icons to those sizes (only that you need) and put them in respective drawable folders. – Niraj Niroula Jan 06 '19 at 05:33

3 Answers3

3

Option 1 - Make sure the Google Sign-in is enabled in the Firebase Authentication methods in Firebase console. By default, Google Sign-in is not enabled.

Option 2 - Inside your AndroidManifest.xml file, under the tag add the following lines to support high memory support in case the Google Sign-in popup requires more memory. Even large images can be loaded using this command in application tag - largeHeap as true ~ your launcher image in this case.

<application
    android:hardwareAccelerated="true"
    android:largeHeap="true" >

Option 3 - Try this code to implement the Google Sign-in using Firebase and it should work.

public class LoginActivity extends AppCompatActivity {

private GoogleSignInClient mGoogleSignInClient;
private FirebaseAuth mAuth;
private int permissions = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    SignInButton authButton = findViewById(R.id.home_auth_button);
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken("xxxxxxxxxxxx.apps.googleusercontent.com").requestEmail().build();
    mAuth = FirebaseAuth.getInstance();
    mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
    authButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            signIn();
        }
    });
}

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

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 0) {
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        try {
            GoogleSignInAccount account = task.getResult(ApiException.class);
            if (account != null) {
                firebaseAuthWithGoogle(account);
            } else{
                Log.w("AUTH", "Account is NULL");
                Toast.makeText(LoginActivity.this, "Sign-in failed, try again later.", Toast.LENGTH_LONG).show();
            }
        } catch (ApiException e) {
            Log.w("AUTH", "Google sign in failed", e);
            Toast.makeText(LoginActivity.this, "Sign-in failed, try again later.", Toast.LENGTH_LONG).show();
        }
    }
}

private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
    Log.d("AUTH", "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()) {
                        Log.d("AUTH", "signInWithCredential:success");
                        startActivity(new Intent(LoginActivity.this, AnotherActivity.class));
                        Toast.makeText(LoginActivity.this, "Sign-in successful!", Toast.LENGTH_LONG).show();
                    } else {
                        Log.w("AUTH", "signInWithCredential:failure", task.getException());
                        Toast.makeText(LoginActivity.this, "Sign-in failed, try again later.", Toast.LENGTH_LONG).show();
                    }
                }
            });
    }
}

Look out for the GoogleSignInOptions.Builder where you need to pass the requestIdToken("xxxx") with the builder. It's a URL which you can find it under Firebase Authentication Tab -> Sign-in Methods -> Google -> Web SDK Configuration -> Web Client ID.

requestIdToken Web Client ID

Hope this answers your query.

  • None of the above options work in my case. Can help me find the root cause? – gopalanrc Oct 26 '20 at 04:23
  • I don't why everything else is working but once one gmail account is used for login for the first time then second time it automatically logs in with the same account instead of showing list of gmail accounts or option to add account. What might be the problem ? – Badri Paudel Dec 26 '20 at 17:16
2

So as expected, this was due to

Canvas: trying to draw too large(256000000bytes) bitmap.

The launcher icon that you had used, which also appeared in the account chooser dialog, was stopping the dialog from popping.
As a solution, you may follow Praveen's answer (option2) about making the app support the larger images from Manifest.
But I suggest you to compress the image file because the account chooser dialog doesn't really need a hi-res image and neither the launcher icon need to be that big. Take a look at this, scale the launcher icons to those sizes(only that you need) and put them in respective drawable folders so that it might help you avoid similar issues in future as well.

Niraj Niroula
  • 2,376
  • 1
  • 17
  • 36
0

Google sign in success fully but our api login/sign up response are failed at that time second time click on "Google sing" button at that time Google account selection dialogue not appear,

first of all, check your Google login sign in or not,

and then clear it.

fun googleLogin() {

        val gso = GoogleSignInOptions
            .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestProfile()
            .build()

        val mGoogleSignInClient = GoogleSignIn.getClient(this, gso)

        //check google login sign in or not
        val account = GoogleSignIn.getLastSignedInAccount(this)
        if(account==null){
            val signInIntent = mGoogleSignInClient.signInIntent
            startActivityForResult(signInIntent, REQUEST_CODE_GOOGLE_SIGN_IN)
        }else{
            // clear account  
            revokeAccess(mGoogleSignInClient)
        }

    } 

remove already login account

private fun revokeAccess(mGoogleSignInClient: GoogleSignInClient) {
        mGoogleSignInClient.revokeAccess()
            .addOnCompleteListener(this, OnCompleteListener<Void?> {
                // ...
                val signInIntent = mGoogleSignInClient.signInIntent
                startActivityForResult(signInIntent, REQUEST_CODE_GOOGLE_SIGN_IN)
            })
    }
sajid
  • 179
  • 1
  • 6