首页 > 解决方案 > flutter_facebook_login 插件在 iOS 模拟器上登录问题(使用 Android Studio)

问题描述

我正在使用 Android Studio(一个时间跟踪器,在 Udemy 上的课程之后)构建一个 Flutter 应用程序,并且我正处于创建登录页面的阶段,该页面允许我使用 Google、Facebook、电子邮件登录或“匿名”。我使用的是 flutter_facebook_login 插件的 2.0.1 版本,因为最新版本 3.0.0 会生成许多与 Cocoapods 相关的错误。2.0.1 版解决了所有这些错误。

我正在使用 Flutter 的 firebase_auth 包进行所有身份验证,以便生成唯一的用户 ID,以控制每个用户看到的内容。登录过程分为两个不同的页面。有一个 'auth.dart' 页面处理所有授权工作,包括 Firebase、Google 和 Facebook 等。它看起来像这样:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_facebook_login/flutter_facebook_login.dart';
import 'package:google_sign_in/google_sign_in.dart';

class User {
  User({@required this.uid});
  final String uid;
}

abstract class AuthBase {
  Stream<User> get onAuthStateChanged;
  Future<User> currentUser();
  Future<User> signInAnonymously();
  Future<User> signInWithGoogle();
  Future<User> signInWithFacebook();
  Future<void> signOut();
}

class Auth implements AuthBase {
  final _firebaseAuth = FirebaseAuth.instance;

  User _userFromFirebase(FirebaseUser user) {
    if (user == null) {
      return null;
    }
    return User(uid: user.uid);
  }

  @override
  Stream<User> get onAuthStateChanged {
    return _firebaseAuth.onAuthStateChanged.map(_userFromFirebase);
  }

  @override
  Future<User> currentUser() async {
    final user = await _firebaseAuth.currentUser();
    return _userFromFirebase(user);
  }

  @override
  Future<User> signInAnonymously() async {
    final authResult = await _firebaseAuth.signInAnonymously();
    return _userFromFirebase(authResult.user);
  }

  @override
  Future<User> signInWithGoogle() async {
    final googleSignIn = GoogleSignIn();
    final googleAccount = await googleSignIn.signIn();
    if (googleAccount != null) {
      final googleAuth = await googleAccount.authentication;
      if (googleAuth.accessToken != null && googleAuth.idToken != null) {
        final authResult = await _firebaseAuth.signInWithCredential(
          GoogleAuthProvider.getCredential(
            idToken: googleAuth.idToken,
            accessToken: googleAuth.accessToken,
          ),
        );
        return _userFromFirebase(authResult.user);
      } else {
        throw PlatformException(
          code: 'ERROR_MISSING_GOOGLE_AUTH_TOKEN',
          message: 'Missing Google Auth Token',
        );
      }
    } else {
      throw PlatformException(
        code: 'ERROR_ABORTED_BY_USER',
        message: 'Sign in aborted by user',
      );
    }
  }

  @override
  Future<User> signInWithFacebook() async {
    final facebookLogin = FacebookLogin();
    final result = await facebookLogin.logInWithReadPermissions(
      ['public_profile'],
    );
    if (result.accessToken != null) {
      final authResult = await _firebaseAuth
          .signInWithCredential(FacebookAuthProvider.getCredential(
        accessToken: result.accessToken.token,
      ));
      return _userFromFirebase(authResult.user);
    } else {
      throw PlatformException(
        code: 'ERROR_ABORTED_BY_USER',
        message: 'Sign in aborted by user',
      );
    }
  }

  @override
  Future<void> signOut() async {
    final googleSignIn = GoogleSignIn();
    await googleSignIn.signOut();
    final facebookLogin = FacebookLogin();
    await facebookLogin.logOut();
    await _firebaseAuth.signOut();
  }
}

然后,登录页面,包含所有按钮以及与 Google 和 Facebook 等的交互,如下所示:

import 'package:flutter/material.dart';
import 'package:time_tracker_flutter_course/app/sign_in/sign_in_button.dart';
import 'package:time_tracker_flutter_course/app/sign_in/social_sign_in_button.dart';
import 'package:time_tracker_flutter_course/services/auth.dart';

class SignInPage extends StatelessWidget {
  SignInPage({@required this.auth});
  final AuthBase auth;

  Future<void> _signInAnonymously() async {
    try {
      await auth.signInAnonymously();
    } catch (e) {
      print(e.toString());
    }
  }

  Future<void> _signInWithGoogle() async {
    try {
      await auth.signInWithGoogle();
    } catch (e) {
      print(e.toString());
    }
  }

  Future<void> _signInWithFacebook() async {
    try {
      await auth.signInWithFacebook();
    } catch (e) {
      print(e.toString());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Time Tracker'),
        elevation: 2.0,
      ),
      body: _buildContent(),
      backgroundColor: Colors.grey[200],
    );
  }

  Widget _buildContent() {
    return Padding(
      padding: EdgeInsets.all(16.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Text(
            'Sign In',
            textAlign: TextAlign.center,
            style: TextStyle(
              fontSize: 32.0,
              fontWeight: FontWeight.w600,
            ),
          ),
          SizedBox(height: 48.0),
          SocialSignInButton(
            assetName: 'images/google-logo.png',
            text: 'Sign in with Google',
            textColor: Colors.black87,
            color: Colors.white,
            onPressed: _signInWithGoogle,
          ),
          SizedBox(height: 8.0),
          SocialSignInButton(
            assetName: 'images/facebook-logo.png',
            text: 'Sign in with Facebook',
            textColor: Colors.white,
            color: Color(0xFF334D92),
            onPressed: _signInWithFacebook,
          ),
          SizedBox(height: 8.0),
          SignInButton(
            text: 'Sign in with email',
            textColor: Colors.white,
            color: Colors.teal[700],
            onPressed: () {},
          ),
          SizedBox(height: 8.0),
          Text(
            'or',
            style: TextStyle(fontSize: 14.0, color: Colors.black87),
            textAlign: TextAlign.center,
          ),
          SizedBox(height: 8.0),
          SignInButton(
            text: 'Go anonymous',
            textColor: Colors.black,
            color: Colors.lime[300],
            onPressed: _signInAnonymously,
          ),
        ],
      ),
    );
  }
}

所有这些代码和方法在大多数情况下都能完美运行,其中包括:

当我尝试在 Android Studio 的 iOS 模拟器上使用 Facebook 方法登录时,我遇到了问题。在 Android Studio 控制台中,错误是“吐出”:

flutter: PlatformException(ERROR_ABORTED_BY_USER, Sign in aborted by user, null)

你会从第一块代码('auth.dart' 代码)中看到,这个错误只是我内置的一个通用错误——我根本没有具体说明它。

我不认为问题出在 flutter_facebook_login 插件上,因为它仍然适用于 Android,除非该插件存在 iOS 独有的问题。我认为 Facebook 的 iOS 设置存在问题,即使我已按照信中的说明进行操作,包括使用 Xcode。

有人可以帮助我了解可能导致此错误的原因,以及如何对其进行排序吗?这是设置中唯一可以看到目前在两个模拟器平台上都不起作用的东西。

标签: iosfirebaseandroid-studioflutterfacebook-login

解决方案


我有同样的问题,我认为这是带有 ios beta 版本的 facebook api 的问题。我找到了解决办法。这只是一种解决方法,而不是实际的解决方案。它对我有用,我希望这可以帮助你: -

检查状态何时进入 FacebookLoginStatus.cancelledByUser 的工作,然后使用以下

 facebookLogin.loginBehavior = FacebookLoginBehavior.webViewOnly;

它会强制颤振在 webview 中打开 facebook auth,然后你就可以让它工作了。

看看完整的方法

 Future signInWithFaceBook() async{
   var facebookLogin = new FacebookLogin();
   var result = await facebookLogin.logInWithReadPermissions(['email', 'public_profile']);
   switch (result.status) {
     case FacebookLoginStatus.loggedIn:
       print(result.accessToken.token);
       // Add your route to home page here after sign In
       break;
     case FacebookLoginStatus.cancelledByUser:
    // In your case the program flow will go here as it as a bug with the api I suppose

       facebookLogin.loginBehavior = FacebookLoginBehavior.webViewOnly;
// Once the code comes here the above line will force flutter to open facebook auth in a webview
       result = await facebookLogin.logInWithReadPermissions(['email', 'public_profile']);

       if(result.status==FacebookLoginStatus.loggedIn){
         FirebaseUser user = (await _auth.signInWithCredential(FacebookAuthProvider.getCredential(accessToken: result.accessToken.token)
         )
         ).user;
         final FirebaseUser currentUser = await _auth.currentUser();
         assert(user.uid == currentUser.uid);
         // Add your home page here
       }
       print('CANCELED BY USER');
       break;
     case FacebookLoginStatus.error:
       print(result.errorMessage);
       break;
   }
 }

推荐阅读