skip to Main Content

`I’m creating a role based flutter app where the roles are patient, telenurse, consultant and an admin. I’ve created the login page and everyone is able to log in correctly but when you close the app and come back, it does not keep the user signed in but sends you back to the login screen, how can i fix this problem?

This is what i tried;

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:telenursingapp/admin_portal.dart';
import 'package:telenursingapp/consultant_portal.dart';
import 'package:telenursingapp/patients_portal.dart';
import 'package:telenursingapp/telenurse_portal.dart';

class SignIn extends StatefulWidget {
  const SignIn({super.key});

  @override
  State<SignIn> createState() => _SignInState();
}

class _SignInState extends State<SignIn> {
  // text controllers
bool _isObscure3 = true;
  bool visible = false;
  final _formkey = GlobalKey<FormState>();
  final TextEditingController emailController = new TextEditingController();
  final TextEditingController passwordController = new TextEditingController();

  final _auth = FirebaseAuth.instance;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Container(
              decoration: BoxDecoration(
          gradient: LinearGradient(
              begin: Alignment.topRight,
              end: Alignment.bottomLeft,
              colors: [Colors.blueGrey, Color(0xFF3EB489)]),
        ),
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height * 1.0,
              child: Center(
                child: Container(
                  margin: EdgeInsets.all(12),
                  child: Form(
                    key: _formkey,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        SizedBox(
                          height: 30,
                        ),
                      Image.asset('assets/YourDoc-black.png', width: 70),
                Icon(
                  FontAwesomeIcons.solidHandshake,
                  size: 20,
                  color: Colors.black,
                ),
              SizedBox(height: 80,),

                       Text('Login to your account!', 
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 44,
                        fontWeight: FontWeight.bold
                )),
                const SizedBox(height: 10,),
                const Text('Welcome back to YourDoc',
                style: TextStyle(
                  color: Color.fromARGB(255, 88, 85, 85),
                  fontSize: 24,)),
                        SizedBox(
                          height: 20,
                        ),
                        TextFormField(
                          controller: emailController,
                          decoration: InputDecoration(
                            filled: true,
                            fillColor: Colors.white,
                            hintText: 'Email',
                            enabled: true,
                            contentPadding: const EdgeInsets.only(
                                left: 14.0, bottom: 8.0, top: 8.0),
                            focusedBorder: OutlineInputBorder(
                              borderSide: new BorderSide(color: Colors.white),
                              borderRadius: new BorderRadius.circular(10),
                            ),
                            enabledBorder: UnderlineInputBorder(
                              borderSide: new BorderSide(color: Colors.white),
                              borderRadius: new BorderRadius.circular(10),
                            ),
                          ),
                          validator: (value) {
                            if (value!.length == 0) {
                              return "Email cannot be empty";
                            }
                            if (!RegExp(
                                    "^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+.[a-z]")
                                .hasMatch(value)) {
                              return ("Please enter a valid email");
                            } else {
                              return null;
                            }
                          },
                          onSaved: (value) {
                            emailController.text = value!;
                          },
                          keyboardType: TextInputType.emailAddress,
                        ),
                        SizedBox(
                          height: 20,
                        ),
                        TextFormField(
                          controller: passwordController,
                          obscureText: _isObscure3,
                          decoration: InputDecoration(
                            suffixIcon: IconButton(
                                icon: Icon(_isObscure3
                                    ? Icons.visibility
                                    : Icons.visibility_off),
                                onPressed: () {
                                  setState(() {
                                    _isObscure3 = !_isObscure3;
                                  });
                                }),
                            filled: true,
                            fillColor: Colors.white,
                            hintText: 'Password',
                            enabled: true,
                            contentPadding: const EdgeInsets.only(
                                left: 14.0, bottom: 8.0, top: 15.0),
                            focusedBorder: OutlineInputBorder(
                              borderSide: new BorderSide(color: Colors.white),
                              borderRadius: new BorderRadius.circular(10),
                            ),
                            enabledBorder: UnderlineInputBorder(
                              borderSide: new BorderSide(color: Colors.white),
                              borderRadius: new BorderRadius.circular(10),
                            ),
                          ),
                          validator: (value) {
                            RegExp regex = new RegExp(r'^.{6,}$');
                            if (value!.isEmpty) {
                              return "Password cannot be empty";
                            }
                            if (!regex.hasMatch(value)) {
                              return ("please enter valid password min. 6 character");
                            } else {
                              return null;
                            }
                          },
                          onSaved: (value) {
                            passwordController.text = value!;
                          },
                          keyboardType: TextInputType.emailAddress,
                        ),
                       
                        SizedBox(
                          height: 20,
                        ),
                        MaterialButton(
                          shape: RoundedRectangleBorder(
                              borderRadius:
                                  BorderRadius.all(Radius.circular(20.0))),
                          elevation: 5.0,
                          height: 40,
                          minWidth: 500,
                          onPressed: () {
                            setState(() {
                              visible = true;
                            });
                            signIn(
                                emailController.text, passwordController.text);
                          },
                          color: Color.fromARGB(255, 20, 85, 206),
                          child: Text(
                            "Login",
                            style: TextStyle(
                              fontSize: 20,
                              fontWeight: FontWeight.bold,
                              color: Colors.white,

                            ),
                          ),
                        ),
                        SizedBox(
                          height: 10,
                        ),
                        Visibility(
                            maintainSize: true,
                            maintainAnimation: true,
                            maintainState: true,
                            visible: visible,
                            child: Container(
                                child: CircularProgressIndicator(
                              color: Colors.white,
                            ))),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          
          ],
        ),
      ),
    );
  }

  void route() {
    User? user = FirebaseAuth.instance.currentUser;
    var kk = FirebaseFirestore.instance
            .collection('users')
            .doc(user!.uid)
            .get()
            .then((DocumentSnapshot documentSnapshot) {
      if (documentSnapshot.exists) {
        if (documentSnapshot.get('role') == "Patient") {
           Navigator.pushReplacement(
          context,
          MaterialPageRoute(
            builder: (context) =>  PatientsPortal(),
          ),
        );
        }
        else if(documentSnapshot.get('role') == "Consultant"){
          Navigator.pushReplacement(
          context, 
          MaterialPageRoute(builder: (context) => ConsultantPortal()));
        }
        else if(documentSnapshot.get('role') == "New Admin"){
          Navigator.pushReplacement(
          context, 
          MaterialPageRoute(builder: (context) => AdminPortal()));
        }
        else if(documentSnapshot.get('role') == "Telenurse"){
          Navigator.pushReplacement(
          context, 
          MaterialPageRoute(builder: (context) => TelenursePortal()));
        }
        else{
          Navigator.pushReplacement(
          context,
          MaterialPageRoute(
            builder: (context) =>  SignIn(),
          ),
        );
        }
      } else {
        print('Document does not exist on the database');
      }
    });
  }

  void signIn(String email, String password) async {
    if (_formkey.currentState!.validate()) {
      try {
        UserCredential userCredential =
            await FirebaseAuth.instance.signInWithEmailAndPassword(
          email: email,
          password: password,
        );
        route();
      } on FirebaseAuthException catch (e) {
        if (e.code == 'user-not-found') {
          print('No user found for that email.');
        } else if (e.code == 'wrong-password') {
          print('Wrong password provided for that user.');
        }
      }
    }
  }
}

2

Answers


  1. You should use Hive local DB or Shared Preferences to store one boolean variable locally named isLoggedInUser and once the user logs in you can make this variable as true and default value for this will be false.

    So what happens is that you can check in Splash screen if that flag is true then you will redirect user to Dashboard or else you can redirect user to the Login screen.

    You can also store other variables like user type and their id for further use in the application. This way user will not need to login every-time they open the app.

    Here’s a class which you can use to store and get variables locally.

    import ‘package:shared_preferences/shared_preferences.dart’;

    class MyPrefs {
      Future<void> setValue<T>(String key, T value) async {
        final prefs = await SharedPreferences.getInstance();
    
        if (value is int) {
          prefs.setInt(key, value);
        } else if (value is String) {
          prefs.setString(key, value);
        } else if (value is bool) {
          prefs.setBool(key, value);
        }
      }
    
      Future<T> getValue<T>(String key, T defaultValue) async {
        final prefs = await SharedPreferences.getInstance();
    
        if (defaultValue is String) {
          return (prefs.getString(key) ?? "") as T;
        } else if (defaultValue is int) {
          return (prefs.getInt(key) ?? 0) as T;
        } else {
          return (prefs.getBool(key) ?? false) as T;
        }
      }
    }
    

    Use it like this :

    Set : MyPrefs().setValue("isLoggedInUser", true/false);. <– Here you need to pass true or false as value

    Get : await MyPrefs().getValue("isLoggedInUser", false);. <– Here false is a default value

    Login or Signup to reply.
  2. The Firebase Authentication SDK automatically stores the credentials of the user in local storage and restores them from there when the app restarts.

    Doing this however requires it to make a call to the server, to check if the credentials are still valid and to ensure that the user hasn’t been disabled, and this takes time.

    Instead of making the app wait to render for the first time during this check, the app starts up normally while this is happening. And that runs your build and route for the first time, which (I guess, as I don’t see this code in what you shared) then check FirebaseAuth.instance.currentUser and notes that it is null, so nobody is signed in (yet).

    There is no way to prevent this behavior. So instead you should react to when Firebase has completed its restore flow by listening to the authStateChanges() stream as shown in the first example of the documentation on getting the current user:

    FirebaseAuth.instance
      .authStateChanges()
      .listen((User? user) {
        if (user != null) {
          print(user.uid);
        }
      });
    

    Since you’re likely going to be doing this in the UI, you’ll want to use a StreamBuilder in there to wrap FirebaseAuth.instance.authStateChanges().

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search