Flutter+Firebase 将匿名用户升级到 GoogleSignIn 时出错(给定字符串为空或 null)

Posted

技术标签:

【中文标题】Flutter+Firebase 将匿名用户升级到 GoogleSignIn 时出错(给定字符串为空或 null)【英文标题】:Flutter+Firebase error upgrading anonymous user to GoogleSignIn (Given String is empty or null) 【发布时间】:2019-06-29 23:43:23 【问题描述】:

我在 Flutter 中有一个匿名帐户,我正在尝试使用 Google 的 AuthCredential 对其进行升级。我已验证凭据是使用有效的 accessToken 和 idToken 创建的。

所以如果auth.currentUser() 是我的匿名FirebaseUser,则在下面调用linkAccountToGoogle() 会导致错误。

/// Upgrade an anonymous account by linking it to a Google account.
Future<FirebaseUser> linkAccountToGoogle() async 
  final credential = await _getGoogleAuthCredential();
  if (credential != null) 
    try 
      return auth.linkWithCredential(credential);  // <=== THROWS ERROR
     catch (e) 
      print(e);
    
  
  return null;


/// Tries to sign-in silently first. May return `null`.
Future<AuthCredential> _getGoogleAuthCredential() async 
  GoogleSignInAccount account;
  try 
    account = await _googleAuthService.signInSilently() ??
        await _googleAuthService.signIn();
   catch (e) 
    print(e);
  
  final googleAuth = await account?.authentication;
  if (account == null) 
    print('Unable to retrieve Google account.');
   else if (googleAuth == null) 
    print('Unable to authenticate to Google account ($account.email).');
   else 
    // print(
    //     'accessToken: $googleAuth.accessToken, idToken: $googleAuth.idToken');
    return GoogleAuthProvider.getCredential(
        accessToken: googleAuth.accessToken, idToken: googleAuth.idToken);
  
  return null;

堆栈跟踪

I/flutter ( 3038): Credential: Instance of 'AuthCredential'
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038): Failed to handle method call
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038): java.lang.IllegalArgumentException: Given String is empty or null
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at com.google.android.gms.common.internal.Preconditions.checkNotEmpty(Unknown Source:5)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at com.google.firebase.auth.EmailAuthProvider.getCredential(Unknown Source:2)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at io.flutter.plugins.firebaseauth.FirebaseAuthPlugin.handleLinkWithEmailAndPassword(FirebaseAuthPlugin.java:272)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at io.flutter.plugins.firebaseauth.FirebaseAuthPlugin.onMethodCall(FirebaseAuthPlugin.java:122)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:200)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at io.flutter.view.FlutterNativeView$PlatformMessageHandlerImpl.handlePlatformMessage(FlutterNativeView.java:188)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:202)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at android.os.MessageQueue.next(MessageQueue.java:325)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at android.os.Looper.loop(Looper.java:142)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at android.app.ActivityThread.main(ActivityThread.java:6694)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
E/MethodChannel#plugins.flutter.io/firebase_auth( 3038):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)
E/flutter ( 3038): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(error, Given String is empty or null, null)
E/flutter ( 3038): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:564:7)
E/flutter ( 3038): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:33)
E/flutter ( 3038): <asynchronous suspension>
E/flutter ( 3038): #2      FirebaseAuth.linkWithCredential (file:///home/jacob/.pub-cache/hosted/pub.dartlang.org/firebase_auth-0.8.0+1/lib/src/firebase_auth.dart:371:54)

我的尝试

我尝试链接的 Google 帐户已经是该项目的用户,因此我从 Firebase 控制台中删除了该 Google 用户。然后再次尝试使用flutter clean flutter run

【问题讨论】:

最近的更新似乎有很多错误(可能部分与 AndroidX 升级有关)。我也遇到了其中一些问题,但决定降级。这是一篇谈论更多github.com/flutter/flutter/issues/27156的帖子 @Jacob 您找到解决方案或解决方法了吗?我的项目中也需要这个 实际上没有,还没有。我将google_sign_in 降级为 ^3.0.0 但这不起作用。也许如果我也降级其他 AndroidX 包,我没有花太多时间在它上面。 最近没有更新?? @ShadyBoshra 是的,显然它已在 firebase_auth 0.11.0 中修复 【参考方案1】:

必须先触发 Google 登录流程,然后才能关联要关联的帐户的身份验证凭据。根据给出的错误,Google Sign-in 的 AuthCredential 中的数据很可能丢失了一些东西,这就是它抛出 Given String is empty or null

的原因

我已经使用firebase_auth: ^3.3.4 尝试了下面的代码,它在我身上运行良好,没有问题。

// Trigger Google Auth flow.
final GoogleSignInAccount googleUser = await GoogleSignIn().signIn();

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

// Create a new credential.
final GoogleAuthCredential googleCredential = GoogleAuthProvider.credential(
  accessToken: googleAuth.accessToken,
  idToken: googleAuth.idToken,
);

// Get current anonymous user.
User anonymousUser = auth.currentUser();

// Link anonymous account with Google account.
await anonymousUser.linkWithCredential(googleCredential);

【讨论】:

以上是关于Flutter+Firebase 将匿名用户升级到 GoogleSignIn 时出错(给定字符串为空或 null)的主要内容,如果未能解决你的问题,请参考以下文章

如何将匿名 Firebase 凭据保存到本地存储以外的其他地方?

升级到 Flutter 2.0 会破坏 Flutter Firebase Web 项目

匿名身份验证用户的这个 Firebase/Firestore 安全规则是不是安全?

如何在颤振应用程序中使用相同的 Firebase 匿名用户

使用 SwiftUI、Combine 和 Firebase,我如何在将用户的帐户链接到电子邮件/密码之前验证用户是不是已匿名登录?

Firebase/Flutter - 无法将数据写入数据库