代码之家  ›  专栏  ›  技术社区  ›  Mike1982

flutter firebase google注销不工作

  •  0
  • Mike1982  · 技术社区  · 6 年前

    import 'dart:async';
    import 'package:firebase_auth/firebase_auth.dart';
    import 'package:google_sign_in/google_sign_in.dart';
    
    abstract class BaseAuth {
      Future<String> signIn(String email, String password);
    
      Future<String> signUp(String email, String password);
    
      Future<FirebaseUser> getCurrentUser();
    
      Future<void> sendEmailVerification();
    
      Future<void> signOut();
    
      Future<bool> isEmailVerified();
    
      Future<String> signInWithGoogle();
    }
    
    class Auth implements BaseAuth {
      final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
      final GoogleSignIn googleSignIn = GoogleSignIn();
      FirebaseUser user;
    
      Future<String> signIn(String email, String password) async {
    
        user = (await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password)).user;
        return user.email;
      }
    
      Future<String> signUp(String email, String password) async {
        FirebaseUser user = (await _firebaseAuth.createUserWithEmailAndPassword(
            email: email, password: password)).user;
        return user.uid;
      }
    
      Future<FirebaseUser> getCurrentUser() async {
        user = await _firebaseAuth.currentUser();
        return user;
      }
      signOut() async {
        //print("signed in user: ${authService.user}");
        await _firebaseAuth.signOut();
      }
    
      Future<void> sendEmailVerification() async {
        FirebaseUser user = await _firebaseAuth.currentUser();
        user.sendEmailVerification();
      }
    
      Future<bool> isEmailVerified() async {
        FirebaseUser user = await _firebaseAuth.currentUser();
        return user.isEmailVerified;
      }
    
      Future<String> signInWithGoogle() async {
        final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
        final GoogleSignInAuthentication googleSignInAuthentication =
        await googleSignInAccount.authentication;
    
        final AuthCredential credential = GoogleAuthProvider.getCredential(
          accessToken: googleSignInAuthentication.accessToken,
          idToken: googleSignInAuthentication.idToken,
        );
    
       user = (await _firebaseAuth.signInWithCredential(credential)).user;
    
        assert(!user.isAnonymous);
        assert(await user.getIdToken() != null);
    
        final FirebaseUser currentUser = await _firebaseAuth.currentUser();
        assert(user.uid == currentUser.uid);
        return 'signInWithGoogle succeeded: $user';
      }
    
    }
    
    
    

    另一个奇怪的是,如果我启动应用程序,并已登录(谷歌),我点击注销,它似乎工作。我的控制台中没有任何内容,但它会返回到登录屏幕。然后,如果我以google的身份重新登录并注销,错误就开始发生了。另一件奇怪的事情是,如果我碰巧已经登录,我让它在一次点击后注销,而不做任何更改,如果我在android studio中重新启动我的应用程序,它会把我带回应该已经登录的屏幕。这只发生在Google注销(而不是firebase注销)上。 知道我做错了什么吗?谢谢

    pubspec.yaml

    dependencies:
      firebase_auth: ^0.14.0+5
    
      firebase_database: ^3.0.7
      google_sign_in: ^4.0.7
      firebase_storage:
      image_picker:
      cloud_firestore:
      shared_preferences:
      fluttertoast:
      cached_network_image:
      intl:
    

    import 'package:flutter/material.dart';
    import 'package:pet_helper/chat.dart';
    import 'package:pet_helper/lost_and_found.dart';
    import 'package:pet_helper/pet_adoption.dart';
    import 'authentication.dart';
    
    class HomePage extends StatefulWidget {
      HomePage({Key key, this.auth, this.userId, this.onSignedOut})
          : super(key: key);
    
      final BaseAuth auth;
      final VoidCallback onSignedOut;
      final String userId;
    
      @override
      State<StatefulWidget> createState() => new _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
    
      final GlobalKey<FormState> formKey = GlobalKey<FormState>();
      int _currentIndex = 0;
    
      @override
      void initState() {
        super.initState();
      }
      final List<Widget> _children = [
        new LostAndFoundPage(),
        new PetAdoptionPage(),
        new ChatPage(),
      ];
      _signOut() async {
        try {
          await widget.auth.signOut();
          widget.onSignedOut();
        } catch (e) {
    
          print(e);
        }
      }
    
      onTabTapped(int index) {
        setState(() {
          _currentIndex = index;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
            appBar: new AppBar(
              automaticallyImplyLeading:false,
              title: new Text('Pet Helper'),
              actions: <Widget>[
                new FlatButton(
                    child: new Text('Logout',
                        style: new TextStyle(fontSize: 17.0, color: Colors.white)),
                    onPressed: _signOut)
              ],
            ),
            body: _children[_currentIndex], // new
            bottomNavigationBar: BottomNavigationBar(
              onTap: onTabTapped, // new
              currentIndex: _currentIndex, // new
              items: [
                new BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  title: Text('Lost & Found'),
                ),
                new BottomNavigationBarItem(
                  icon: Icon(Icons.pets),
                  title: Text('Pet Adoption'),
                ),
                new BottomNavigationBarItem(
                    icon: Icon(Icons.person), title: Text('Chat'))
              ],
            ));
      }
    }
    

    
    import 'package:flutter/material.dart';
    import 'package:pet_helper/home_page.dart';
    import 'authentication.dart';
    
    class LoginSignUpPage extends StatefulWidget {
      LoginSignUpPage({this.auth, this.onSignedIn});
    
      final BaseAuth auth;
      final VoidCallback onSignedIn;
    
      @override
      State<StatefulWidget> createState() => new _LoginSignUpPageState();
    }
    
    enum FormMode { LOGIN, SIGNUP }
    class _LoginSignUpPageState extends State<LoginSignUpPage> {
      final _formKey = new GlobalKey<FormState>();
      String _email;
      String _password;
      String _errorMessage;
    
      // Initial form is login form
      FormMode _formMode = FormMode.LOGIN;
      bool _isIos;
      bool _isLoading;
    
      // Check if form is valid before perform login or signup
      bool _validateAndSave() {
        final form = _formKey.currentState;
        if (form.validate()) {
          form.save();
          return true;
        }
        return false;
      }
    
      // Perform login or signup
      void _validateAndSubmit() async {
        setState(() {
          _errorMessage = "";
          _isLoading = true;
        });
        if (_validateAndSave()) {
          String userId = "";
          try {
            if (_formMode == FormMode.LOGIN) {
              userId = await widget.auth.signIn(_email, _password);
              print('Signed in: $userId');
            } else {
              userId = await widget.auth.signUp(_email, _password);
              widget.auth.sendEmailVerification();
              _showVerifyEmailSentDialog();
              print('Signed up user: $userId');
            }
            setState(() {
              _isLoading = false;
            });
    
            if (userId.length > 0 && userId != null && _formMode == FormMode.LOGIN) {
              widget.onSignedIn();
            }
    
          } catch (e) {
            print('Error: $e');
            setState(() {
              _isLoading = false;
              if (_isIos) {
                _errorMessage = e.details;
              } else
                _errorMessage = 'Incorrect user or password';
            });
          }
        }
      }
    
    
      @override
      void initState() {
        _errorMessage = "";
        _isLoading = false;
        super.initState();
      }
    
      void _changeFormToSignUp() {
        _formKey.currentState.reset();
        _errorMessage = "";
        setState(() {
          _formMode = FormMode.SIGNUP;
        });
      }
    
      void _changeFormToLogin() {
        _formKey.currentState.reset();
        _errorMessage = "";
        setState(() {
          _formMode = FormMode.LOGIN;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        _isIos = Theme.of(context).platform == TargetPlatform.iOS;
        return new Scaffold(
            appBar: new AppBar(
              title: new Text('Pet Helper'),
            ),
            body: Stack(
              children: <Widget>[
                _showBody(),
                _showCircularProgress(),
              ],
            ));
      }
    
      Widget _showCircularProgress(){
        if (_isLoading) {
          return Center(child: CircularProgressIndicator());
        } return Container(height: 0.0, width: 0.0,);
    
      }
    
      void _showVerifyEmailSentDialog() {
        showDialog(
          context: context,
          builder: (BuildContext context) {
            // return object of type Dialog
            return AlertDialog(
              title: new Text("Verify your account"),
              content: new Text("Link to verify account has been sent to your email"),
              actions: <Widget>[
                new FlatButton(
                  child: new Text("Dismiss"),
                  onPressed: () {
                    _changeFormToLogin();
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
      }
    
      Widget _showBody(){
        return new Container(
            padding: EdgeInsets.all(16.0),
            child: new Form(
              key: _formKey,
              child: new ListView(
                shrinkWrap: true,
                children: <Widget>[
                  _showLogo(),
                  _showEmailInput(),
                  _showPasswordInput(),
                  _showErrorMessage(),
                  _showPrimaryButton(),
                  _showSecondaryButton(),
                  _googleSignInButton(),
    
                ],
              ),
            ));
      }
    
      Widget _showErrorMessage() {
        if (_errorMessage.length > 0 && _errorMessage != null) {
          return new Text(
            _errorMessage,
            style: TextStyle(
                fontSize: 13.0,
                color: Colors.red,
                height: 1.0,
                fontWeight: FontWeight.w300),
          );
        } else {
          return new Container(
            height: 0.0,
          );
        }
      }
    
      Widget _showLogo() {
        return new Hero(
          tag: 'hero',
          child: Padding(
            padding: EdgeInsets.fromLTRB(0.0, 30.0, 0.0, 0.0),
            child: CircleAvatar(
              backgroundColor: Colors.transparent,
              radius: 120.0,
              child: Image.asset('assets/babies.png'),
            ),
          ),
        );
      }
    
      Widget _showEmailInput() {
        return Padding(
          padding: const EdgeInsets.fromLTRB(0.0, 25.0, 0.0, 0.0),
          child: new TextFormField(
            maxLines: 1,
            keyboardType: TextInputType.emailAddress,
            autofocus: false,
            decoration: new InputDecoration(
                hintText: 'Email',
                icon: new Icon(
                  Icons.mail,
                  color: Colors.grey,
                )),
            validator: (String value) {
            if (value.isEmpty) {
              _isLoading = false;
              return 'Email can\'t be empty';
            }
            else{
              return null;
            }
          },
            onSaved: (value) => _email = value.trim(),
          ),
        );
      }
    
      Widget _showPasswordInput() {
        return Padding(
          padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0),
          child: new TextFormField(
            maxLines: 1,
            obscureText: true,
            autofocus: false,
            decoration: new InputDecoration(
                hintText: 'Password',
                icon: new Icon(
                  Icons.lock,
                  color: Colors.grey,
                )),
            validator: (String value) {
              if (value.isEmpty) {
                _isLoading = false;
                return 'Password can\'t be empty';
              }
              else{
                return null;
              }
            },
            onSaved: (value) => _password = value.trim(),
          ),
        );
      }
    
      Widget _showSecondaryButton() {
        return new FlatButton(
          child: _formMode == FormMode.LOGIN
              ? new Text('Create an account',
              style: new TextStyle(fontSize: 18.0, fontWeight: FontWeight.w300))
              : new Text('Have an account? Sign in',
              style:
              new TextStyle(fontSize: 18.0, fontWeight: FontWeight.w300)),
          onPressed: _formMode == FormMode.LOGIN
              ? _changeFormToSignUp
              : _changeFormToLogin,
        );
      }
    
      Widget _showPrimaryButton() {
        return new Padding(
            padding: EdgeInsets.fromLTRB(0.0, 35.0, 0.0, 0.0),
            child: SizedBox(
              height: 40.0,
              child: new RaisedButton(
                elevation: 5.0,
                shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(30.0)),
                color: Colors.blue,
                child: _formMode == FormMode.LOGIN
                    ? new Text('Login',
                    style: new TextStyle(fontSize: 20.0, color: Colors.white))
                    : new Text('Create account',
                    style: new TextStyle(fontSize: 20.0, color: Colors.white)),
                onPressed: _validateAndSubmit,
              ),
            ));
      }
    
    void submitGoogleLogin() async{
      setState(() {
        _errorMessage = "";
        _isLoading = true;
      });
      String userId = "";
      userId = await widget.auth.signInWithGoogle().whenComplete(() {
        widget.onSignedIn();
        Navigator.of(context).push(
          MaterialPageRoute(
            builder: (context) {
              return new HomePage();
            },
          ),
        );
      });
      print('Signed in: $userId');
    }
    
      Widget _googleSignInButton() {
        return OutlineButton(
          splashColor: Colors.grey,
          onPressed: submitGoogleLogin,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
          highlightElevation: 0,
          borderSide: BorderSide(color: Colors.grey),
          child: Padding(
            padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Image(image: AssetImage("assets/google_logo.png"), height: 30.0),
                Padding(
                  padding: const EdgeInsets.only(left: 10),
                  child: Text(
                    'Sign in with Google',
                    style: TextStyle(
                      fontSize: 15,
                      color: Colors.grey,
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      }
    }
    
    
    
    

    和根页面更改用户的状态:

    import 'package:flutter/material.dart';
    import 'login_signup_page.dart';
    import 'authentication.dart';
    import 'home_page.dart';
    
    class RootPage extends StatefulWidget {
      RootPage({this.auth});
    
      final BaseAuth auth;
    
      @override
      State<StatefulWidget> createState() => new _RootPageState();
    }
    
    enum AuthStatus {
      NOT_DETERMINED,
      NOT_LOGGED_IN,
      LOGGED_IN,
    }
    
    class _RootPageState extends State<RootPage> {
      AuthStatus authStatus = AuthStatus.NOT_DETERMINED;
      String _userId = "";
    
      @override
      void initState() {
        super.initState();
        widget.auth.getCurrentUser().then((user) {
          setState(() {
            if (user != null) {
              _userId = user?.uid;
            }
            authStatus =
            user?.uid == null ? AuthStatus.NOT_LOGGED_IN : AuthStatus.LOGGED_IN;
          });
        });
      }
    
      void _onLoggedIn() {
        widget.auth.getCurrentUser().then((user){
          setState(() {
            _userId = user.uid.toString();
          });
        });
        setState(() {
          authStatus = AuthStatus.LOGGED_IN;
    
        });
      }
    
      void _onSignedOut() {
        setState(() {
          authStatus = AuthStatus.NOT_LOGGED_IN;
          _userId = "";
        });
      }
    
      Widget _buildWaitingScreen() {
        return Scaffold(
          body: Container(
            alignment: Alignment.center,
            child: CircularProgressIndicator(),
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        switch (authStatus) {
          case AuthStatus.NOT_DETERMINED:
            return _buildWaitingScreen();
            break;
          case AuthStatus.NOT_LOGGED_IN:
            return new LoginSignUpPage(
              auth: widget.auth,
              onSignedIn: _onLoggedIn,
            );
            break;
          case AuthStatus.LOGGED_IN:
            if (_userId.length > 0 && _userId != null) {
              return new HomePage(
                userId: _userId,
                auth: widget.auth,
                onSignedOut: _onSignedOut,
              );
            } else return _buildWaitingScreen();
            break;
          default:
            return _buildWaitingScreen();
        }
      }
    }
    
    
    

    初始化根页

    void main() async{
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
            title: 'Pet Helper',
            debugShowCheckedModeBanner: false,
            theme: new ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: new RootPage(auth: new Auth()));
      }
    }
    
    1 回复  |  直到 6 年前
        1
  •  5
  •   Benjamin user12576004    6 年前
    abstract class BaseAuth {
      Future<String> signIn(String email, String password);
    
      Future<String> signUp(String email, String password);
    
      Future<FirebaseUser> getCurrentUser();
    
      Future<void> sendEmailVerification();
    
      Future<void> signOut();
    
      Future<bool> isEmailVerified();
    
      Future<String> signInWithGoogle();
    
      void signOutGoogle();
    }
    
    class Auth implements BaseAuth {
      final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
      final GoogleSignIn googleSignIn = GoogleSignIn();
      FirebaseUser user;
    
      Future<String> signIn(String email, String password) async {
    
        user = (await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password)).user;
        return user.email;
      }
    
      Future<String> signUp(String email, String password) async {
        FirebaseUser user = (await _firebaseAuth.createUserWithEmailAndPassword(
            email: email, password: password)).user;
        return user.uid;
      }
    
      Future<FirebaseUser> getCurrentUser() async {
        user = await _firebaseAuth.currentUser();
        return user;
      }
      signOut() async {
        print("signed in user: $user");
        await _firebaseAuth.signOut();
      }
    
      Future<void> sendEmailVerification() async {
        FirebaseUser user = await _firebaseAuth.currentUser();
        user.sendEmailVerification();
      }
    
      Future<bool> isEmailVerified() async {
        FirebaseUser user = await _firebaseAuth.currentUser();
        return user.isEmailVerified;
      }
    
      Future<String> signInWithGoogle() async {
        final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
        final GoogleSignInAuthentication googleSignInAuthentication =
        await googleSignInAccount.authentication;
    
        final AuthCredential credential = GoogleAuthProvider.getCredential(
          accessToken: googleSignInAuthentication.accessToken,
          idToken: googleSignInAuthentication.idToken,
        );
    
       user = (await _firebaseAuth.signInWithCredential(credential)).user;
    
        assert(!user.isAnonymous);
        assert(await user.getIdToken() != null);
    
        final FirebaseUser currentUser = await _firebaseAuth.currentUser();
        assert(user.uid == currentUser.uid);
        return 'signInWithGoogle succeeded: $user';
      }
    }
    
    final Auth authService = Auth(); // add this to the bottom outside the class
    

    所以让我解释一下。每次你打电话 Auth() ,它将创建该类的新实例。因此,在一个实例中,您可以让用户登录。在另一个实例中,您可以注销用户。变量将包含不同的变量值。因此,如果您使用不同的实例来注销用户,而不是登录用户,那么用户变量将为null,因此不允许您注销用户并打印null。

    解决方案

    var authService = Auth();

    将变量放在Auth类之外,这样就可以在任何类、任何地方访问它

        2
  •  0
  •   Mike1982    6 年前

    谢谢大家的回答和支持。我发现了问题。登录谷歌时,widget.onSignedIn 将我重定向到主页(在根页面中)。在调用SignedIn之后,我在google登录按钮中重定向到主页,这就是我丢失用户变量范围的原因。谢谢大家!