'Canceling Google Sign In cause an exception in Flutter

I am trying to implement Google Sign In in my android flutter app, but I have this problem:

When user cancel Google sign in (tap on back button) this exception is throw.

PlatformException (PlatformException(sign_in_canceled, com.google.android.gms.common.api.ApiException: 12501: , null))

I found that from some newer version this should be fixed and it should return null instead of an exception. Currently I am using google_sign_in: ^4.1.1

I tried to wrap my code inside try-catch block or using .catchError() on the method, but nothing help.

My code looks like this:

  Future googleSign(BuildContext context) async {
    final GoogleSignInAccount googleSignInAccount =
        await googleSignIn.signIn().catchError((onError) => print(onError));

    final GoogleSignInAuthentication googleSignInAuthentication =
        await googleSignInAccount.authentication;

    final AuthCredential credential = GoogleAuthProvider.getCredential(
      accessToken: googleSignInAuthentication.accessToken,
      idToken: googleSignInAuthentication.idToken,
    );

    final AuthResult authResult = await _auth.signInWithCredential(credential);

    return authResult.user.uid;
  }

Do you have any idea, how to handle this exception? Thanks.



Solution 1:[1]

The issue seems to be caused by an inability of the Dart VM to correctly detect exceptions that are caught with catchError() as explained in this StackOverflow question

There doesn't seem to be a perfect fix to this bug. However, I came across a somewhat good workaround on Github.

It requires you to edit package:flutter/src/services/platform_channel.dart.

You would have to wrap this ??

final Map<dynamic, dynamic> result = await invokeMethod<Map<dynamic, dynamic>>(method, arguments);
return result?.cast<K, V>();

with a try/catch block as follows ?? (found at the beginning of invokeMapMethod)

try {
    final Map<dynamic, dynamic> result = await invokeMethod<Map<dynamic, dynamic>>(method, arguments);
    return result?.cast<K, V>();
} on PlatformException catch (err) { // Checks for type PlatformException
    if (err.code == 'sign_in_canceled') { // Checks for sign_in_canceled exception
        print(err.toString());
    } else {
        throw err; // Throws PlatformException again because it wasn't the one we wanted
    }
}

You might also want to check if googleSignInAccount is null in which case, you should return return null to prevent further exceptions like NoSuchMethodError: The getter 'authentication' was called on null

So, your code can be re-written as

...

final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn().catchError((onError) => print(onError));

// Return null to prevent further exceptions if googleSignInAccount is null
if (googleSignInAccount == null) return null;

final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;

...

I hope this is easy to follow and it actually works for you. ?

Solution 2:[2]

This issue only resides in debug mode. If the user cancels the Google Sign In then the app won't freeze or crash in the release mode. So, no need to worry as this won't create any problem in the release mode.

Solution 3:[3]

I think u run with debugging mode. So, flutter show every single error, it is ok if u fix or not. So, try to run with without debugging mode and the error will fix, this will not throw the error anymore.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Zamorite
Solution 2 Ahmad Khan
Solution 3 Thet Paing