Flutter Google 登录 - 电子邮件数据返回 null

Posted

技术标签:

【中文标题】Flutter Google 登录 - 电子邮件数据返回 null【英文标题】:Flutter Google Sign In - Email data returns null 【发布时间】:2020-05-04 19:57:03 【问题描述】:

。日志如下。非常感谢您。

我使用 Firebase。

我想用 Google 登录,但是 AuthResult.user.email == null

------------日志错误--------------- -------------

D/FirebaseAuth( 5302): Notifying id token listeners about user ( 9uKLCYS4VwUbuu77KS27bWjKrlI2 ).
I/flutter ( 5302): Result : Poyraz Çakmak https://lh3.googleusercontent.com/a-/AAuE7mABS7DqwgoIHuFfIwNw_574FRdvxKuvVyNarFo0_w=s96-c null
I/flutter ( 5302): NoSuchMethodError: The method 'indexOf' was called on null.
I/flutter ( 5302): Receiver: null
I/flutter ( 5302): Tried calling: indexOf("@")

因为用户模型来自用户名格式。 => 尝试调用:indexOf("@")

GoogleSignIn 方法:

@override
Future<User> login() async 
final GoogleSignInAccount googleSignInAccount =
    await MyToolsFirebase.googleSignIn.signIn();

if (googleSignInAccount != null) 
  GoogleSignInAuthentication googleSignInAuthentication =
      await googleSignInAccount.authentication;

  final String idToken = googleSignInAuthentication.idToken;
  final String accessToken = googleSignInAuthentication.accessToken;

  if (idToken != null && accessToken != null) 
    AuthResult authResult = await MyToolsFirebase.firebaseAuth
        .signInWithCredential(GoogleAuthProvider.getCredential(
            idToken: idToken, accessToken: accessToken));

    return await MyToolsFirebase.saveDbUser(firebaseUser: authResult.user);
  

return null;

MyToolsFirebase 类:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:live_chat/Models/User.dart';

class MyToolsFirebase 

  static final FirebaseAuth firebaseAuth = FirebaseAuth.instance;

  static final GoogleSignIn googleSignIn = GoogleSignIn(
    scopes: <String>[
      'https://www.googleapis.com/auth/contacts.readonly',
      'https://www.googleapis.com/auth/plus.login',
      'https://www.googleapis.com/auth/userinfo.email'
    ],
  );

  static final Firestore firestore = Firestore.instance;

  static User userFromFirebaseUser(@required FirebaseUser firebaseUser) 
    if (firebaseUser == null) return null;
    print("Result : $firebaseUser.displayName $firebaseUser.photoUrl $firebaseUser.email");
    return User(
      uid: firebaseUser.uid,
      email: firebaseUser.email,
      name: firebaseUser.displayName,
      imageURL: firebaseUser.photoUrl,
    );
  


  static Future<User> saveDbUser(@required FirebaseUser firebaseUser) async 
    User user = userFromFirebaseUser(firebaseUser: firebaseUser);
    Map userMap = user.toMap();

    await firestore.collection("users").document(user.uid).setData(userMap);
    return await getDbUser(user.uid);
  

  static Future<User> getDbUser(String uid) async 
    DocumentSnapshot documentSnapshot = await Firestore.instance.collection("users").document(uid).get();
    print(User.fromMap(documentSnapshot.data).toString());
    return User.fromMap(documentSnapshot.data);
  

用户模型:

class User 
  final String uid;
  String email;
  String userName;
  String name;
  String imageURL;
  int level;
  DateTime createdAt;
  DateTime updatedAt;

  User(
    @required this.uid,
    @required this.email,
    this.userName,
    this.name,
    this.imageURL,
    this.level,
    this.createdAt,
    this.updatedAt,
  );

  User.fromMap(Map<String, dynamic> map)
      : this.uid = map["uid"],
        this.email = map["email"],
        this.userName = map["userName"],
        this.name = map["name"],
        this.imageURL = map["imageURL"],
        this.level = int.parse(map["level"]),
        this.createdAt = (map["createdAt"] as Timestamp).toDate(),
        this.updatedAt = (map["updatedAt"] as Timestamp).toDate();

  Map<String, dynamic> toMap() 
    DateTime now = DateTime.now().toLocal().toUtc();
    return 
      'uid': this.uid,
      'email': this.email,
      'userName': this.userName ?? this.email.substring(0, this.email.indexOf("@")) + Random().nextInt(1000).toString(),
      'name': this.name,
      'imageURL': this.imageURL ?? "https://www.logolynx.com/images/logolynx/61/61ba01858af7f2ea1184238e9f2771f2.png",
      'level': this.level ?? 1,
      'createdAt': this.createdAt ?? now,
      'updatedAt': this.updatedAt ?? now,
    ;
  

【问题讨论】:

我也面临同样的问题。有什么解决办法吗?? 这里也一样,我可以得到 user.displayName 和 user.photoUrl 但 user.email 在 assert(user.email != null) 上返回 null; 【参考方案1】:
     @override
  Future<User> signInWithGoogle() async 
    GoogleSignIn _googleSignIn = GoogleSignIn();
    GoogleSignInAccount _googleUser = await _googleSignIn.signIn();
    String _googleUserEmail = _googleUser.email; //BURADA GMAİL OTURUMUNDAN
    // DİREKT OLARAK MAİL ADRESİNİ ALMAYA ÇALIŞIYORUM.
    if (_googleUser != null) 
      GoogleSignInAuthentication _googleAuth = await _googleUser.authentication;
      if (_googleAuth.idToken != null && _googleAuth.accessToken != null) 
        AuthResult sonuc = await _firebaseAuth.signInWithCredential(
            GoogleAuthProvider.getCredential(
                idToken: _googleAuth.idToken,
                accessToken: _googleAuth.accessToken));
        FirebaseUser _user = sonuc.user;
        sonuc.user.updateEmail(_googleUserEmail);
        //Burada Email Adresini Güncelliyoruz.
        //Böylece null olan değer doluyor.
        return _userFromFirebase(_user);
       else 
        return null;
      
     else 
      return null;
    
  

【讨论】:

以上是关于Flutter Google 登录 - 电子邮件数据返回 null的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Firebase Google Apple Facebook 登录

在 Flutter 中使用 Google 登录获取用户的生日/性别

请求的身份验证范围不足 - 在 Flutter 中使用 Firebase 从 Google 登录获取生日时出错

Flutter:如何从谷歌登录firebase获取生日? (安卓和iOS)

使用 Flutter 的电子邮件进行 Firebase 身份验证

Firebase + Flutter:获取用于登录的平台用户