繁体   English   中英

Flutter:取消 Google 登录流程时出现平台异常

[英]Flutter: Platform Exception upon cancelling Google Sign In flow

这是我的 pubspec.yaml。 我正在使用 Flutter:

  dependencies:
    flutter:
      sdk: flutter

    cupertino_icons: ^0.1.2
    http: ^0.11.3

    #Google Sign In
    google_sign_in: 3.0.3
    firebase_auth: ^0.5.18
    flutter_svg: ^0.5.0

我可以很好地进行身份验证,登录结构可以正常工作,但是如果我在 Google 登录并且我通过点击物理设备(S7 Edge)上的后退按钮取消了 Google 的身份验证流程,应用程序将锁定并返回:

Exception has occurred.
PlatformException(sign_in_failed, Status{statusCode=ERROR, resolution=null}, null)

这是情况的日志。 在我看来,它好像默默地失败了:

I/InputMethodManager(13050): startInputInner - mService.startInputOrWindowGainedFocus
D/ViewRootImpl@3c3c6cd[SignInHubActivity](13050): MSG_WINDOW_FOCUS_CHANGED 0
D/ViewRootImpl@3c3c6cd[SignInHubActivity](13050): MSG_WINDOW_FOCUS_CHANGED 1
V/InputMethodManager(13050): Starting input: tba=android.view.inputmethod.EditorInfo@4d4a683 nm : com.xYNP82hMsgxfvzA.pqfrontend ic=null
I/InputMethodManager(13050): startInputInner - mService.startInputOrWindowGainedFocus
D/ViewRootImpl@3c3c6cd[SignInHubActivity](13050): MSG_WINDOW_FOCUS_CHANGED 0
D/ViewRootImpl@a981422[MainActivity](13050): MSG_WINDOW_FOCUS_CHANGED 1
    V/InputMethodManager(13050): Starting input: tba=android.view.inputmethod.EditorInfo@5990000 nm : com.xYNP82hMsgxfvzA.pqfrontend ic=null
I/InputMethodManager(13050): startInputInner - mService.startInputOrWindowGainedFocus
I/FlutterActivityDelegate(13050): onResume setting current activity to this
D/OpenGLRenderer(13050): eglDestroySurface = 0x7cb041df50
D/ViewRootImpl@3c3c6cd[SignInHubActivity](13050): Relayout returned: old=[0,0][1440,2560] new=[0,0][1440,2560] result=0x5 surface={valid=false 0} changed=true
D/ViewRootImpl@3c3c6cd[SignInHubActivity](13050): dispatchDetachedFromWindow
D/InputEventReceiver(13050): channel 'a2e7010 com.xYNP82hMsgxfvzA.pqfrontend/com.google.android.gms.auth.api.signin.internal.SignInHubActivity (client)' ~ Disposing input event receiver.
D/InputEventReceiver(13050): channel 'a2e7010 com.xYNP82hMsgxfvzA.pqfrontend/com.google.android.gms.auth.api.signin.internal.SignInHubActivity (client)' ~NativeInputEventReceiver.

网上没找到解决办法,谁能帮帮我?

更新:我刚刚在日志中收到异常通知:

E/flutter (13050): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (13050): PlatformException(sign_in_failed, Status{statusCode=ERROR, resolution=null}, null)
E/flutter (13050): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:547:7)
E/flutter (13050): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:279:18)
E/flutter (13050): <asynchronous suspension>
E/flutter (13050): #2      GoogleSignIn._callMethod (package:google_sign_in/google_sign_in.dart:183:58)
E/flutter (13050): <asynchronous suspension>
E/flutter (13050): #3      GoogleSignIn._addMethodCall (package:google_sign_in/google_sign_in.dart:222:20)
E/flutter (13050): #4      GoogleSignIn.signIn (package:google_sign_in/google_sign_in.dart:293:48)
E/flutter (13050): #5      handleSignIn (file:///C:/Users/dark_/picquest-dev/pq_frontend/lib/src/services/auth.dart:9:62)
E/flutter (13050): <asynchronous suspension>
E/flutter (13050): #6      main (file:///C:/Users/dark_/picquest-dev/pq_frontend/lib/main.dart:18:10)
E/flutter (13050): <asynchronous suspension>
E/flutter (13050): #7      _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:279:19)
E/flutter (13050): #8      _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:165:12)

它指向我写的身份验证服务:这是:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'dart:async';

final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;

Future<FirebaseUser> handleSignIn() async {
  final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
  final GoogleSignInAuthentication googleAuth = await googleUser.authentication;

  final FirebaseUser user = await _auth.signInWithGoogle(
    accessToken: googleAuth.accessToken,
    idToken: googleAuth.idToken,
  );
  print("signed in " + user.displayName);
  return user;
}


Future<Null> handleSignOut() async {
  await _auth.signOut();
  await _googleSignIn.signOut();
}

这就是所谓的:

void main()  {
  //Default unauthenticated home page

  try {
    auth.handleSignIn();
  } catch(e) {
    print(e);
  }

  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown
    ]);

    runApp(new MaterialApp(
      title: 'Test',
      home: _defaultHome,
      theme: new ThemeData(
        primaryColor: Colors.white
      ),
      routes: <String, WidgetBuilder> {
        '/onboarding/basic-info': (BuildContext context) => new UserOnBoarding_BasicInfo_Page(),
        //'/onboarding/interests': (BuildContext context) => new UserOnBoarding_Interests_Page(),
        '/avatar-repository': (BuildContext context) => new AvatarRepositoryPage(),
        '/login': (BuildContext context) => new LoginPage(),
        '/app/settings': (BuildContext context) => new AppSettingsPage()
      },
    )
  );
} 

您可以使用catchError捕获错误,如下所示:

      Future<FirebaseUser> handleSignIn() async {
        final GoogleSignInAccount googleUser =
            await _googleSignIn.signIn().catchError((onError) {
          print("Error $onError");
        });
        if (googleUser != null) {
          final GoogleSignInAuthentication googleAuth =
              await googleUser.authentication;
          final FirebaseUser user = await _auth
              .signInWithGoogle(
            accessToken: googleAuth.accessToken,
            idToken: googleAuth.idToken,
          )
              .catchError((onError) {
            print("error $onError");
          });
          if (user != null) {
            print("signed in " + user.displayName);
            return user;
          }
        }

        return null;
      }

根据google_sign_in.dart signIn()函数的评论,请求取消应该返回null而不是抛出PlatformException

/// Returned Future resolves to an instance of [GoogleSignInAccount] for a /// successful sign in or `null` in case sign in process was aborted.

我在此处的 Flutter 存储库中针对此错误提出了问题

现在,您必须坚持手动捕获错误

正如@monojmnj 所说,在发布模式下不会发生此错误,我认为这是 IDE 导致的错误,因为当您在终端中运行您的应用程序时,不会导致任何异常。

我可以确认这个问题截至今天仍然存在(但仅在调试模式下) ,并且当在发布模式下取消登录时,应用程序不会崩溃/冻结并继续运行,所以我觉得这主要是抛出的 ide异常和 dart 无法捕获它。所以直到它得到修复,所以一个简单的解决方法是使用应用程序的发布版本。

注意:确保对应用程序进行签名并在 firebase 控制台中输入哈希值,否则 google 登录将无法在发布模式下工作

我最近也遇到了这个错误,我发现.catchError()回调没有在调试模式下被调用(当你在 VSCode 中点击Run->Start Debugging按钮时)。

但是,当您输入 flutter run -d 时, .catchError()方法会被回调,因为它不在调试模式下。

要获得首选模拟器的代码,请在终端中粘贴以下代码行:

instruments -s devices

如果这不起作用,您也可以尝试粘贴以下内容:

xcrun simctl list

.catchError()方法将像以前一样被调用,并且其中的代码将按预期执行!

此外,应用程序不会再因PlatformException()而崩溃,而是您将获得如下日志:

[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The getter 'uid' was called on null.
Receiver: null

我在 Google Sign In 中也.catchError()过这个问题,其中.catchError()没有被调用!

总之,如果您在处理 Firebase 身份验证中的错误时遇到一些错误,您应该首先尝试首先通过终端运行。 谢谢,我希望这会有所帮助!

系统映像需要“ google playstore服务

例如:Google Play Intel x86 Atom System Image(系统映像; android28; google_apis_playstore ; x86)

在使用Google登录之前,请确保您的系统映像具有“ google paly service ”。 通过AVD管理员检查。 如果您的模拟器的系统映像包含“ google paly service ”,您将在模拟器名称旁边看到“ google paly ”图标。

我在此处找到的中断 Google 登录流程的一种解决方法是执行以下操作:

找到包: package:flutter/src/services/platform_channel.dart并更改:

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

到:

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
    }
}

截至今天,我的发布版本遇到了这个问题。 在调试模式下取消 Google 登录工作正常。 在进行发布构建并上传到 TestFlight 后,当我尝试此功能时,该应用程序会崩溃。 甚至我的应用也因此被 App Store 拒绝。 Android build thou 我没有遇到这个问题。 修复此错误的唯一方法是添加 null 检查。 即使用 try 也能捕捉到 IoS App 曾经崩溃过。 希望这对与我在同一条船上的人有所帮助,因为我花了 3 天时间才弄清楚并解决了它

 try {
  // Trigger the authentication flow
  final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
  if(googleUser == null){
    return LoginUserData(functionRespData: FunctionRespData( error: "login-error"));
  }

  // Obtain the auth details from the request
  final GoogleSignInAuthentication? googleAuth =
      await googleUser?.authentication;

  // Create a new credential
  final credential = GoogleAuthProvider.credential(
    accessToken: googleAuth?.accessToken,
    idToken: googleAuth?.idToken,
  );
  // UserCredential? userCredential = await FirebaseAuth.instance.currentUser
  //     ?.linkWithCredential(credential);
  // Once signed in, return the UserCredential
  UserCredential userCredential =
      await FirebaseAuth.instance.signInWithCredential(credential);

  return LoginUserData(userData:_userFromFirebase(userCredential.user));
} on FirebaseAuthException catch (e) {
  return LoginUserData(functionRespData: FunctionRespData(error: e.message));
} catch(e){
  return LoginUserData(functionRespData: FunctionRespData( error: "login-error"));
}

如果您取消流程,对final GoogleSignInAccount googleUser = await _googleSignIn.signIn()的调用将返回 null 值。 流的 rest 取决于不是 null 的值,所以如果是这种情况,请尽早返回。

final GoogleSignInAccount googleUser = await _googleSignIn.signIn()
if (googleUser == null) {
  return; // or throw an error
}

在我的项目案例中

只需通过终端运行它,当您使用 vscode (f5) 运行时会发生这种情况,但是当您在终端上使用flutter run时,不会发生异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM