Bishal Das
Bishal Das

Reputation: 839

How to use shared preferences to keep user logged in flutter?

I want to keep the user logged in after the user successfully logsin in flutter. I am using a REST API to retrieve the user name and password of the user. But I want to save those details so that the user can stay logged in. My current situation is i can successfully log the user in but when i restart the app i have to login again so i need to save the details of the user in a shared preference so that the user can stay logged for the entire session until logout.But i am unable to do that so please help me with it. Thanks in advance

This is the code i have for my login page. I have removed the UI contents which should be inside the listview as those are not that relevant.

Login.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:restaurant_app/globalVar.dart';
import 'package:restaurant_app/homescreen.dart';
import 'package:restaurant_app/models/auth.dart';
import 'package:restaurant_app/signup.dart';
import 'package:http/http.dart' as http;
import 'package:restaurant_app/utils/authutils.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SignIn extends StatefulWidget {

    SignIn({ Key key, this.post }): super(key: key);

@override
_SignInState createState() => _SignInState();
    }

class _SignInState extends State<SignIn> with SingleTickerProviderStateMixin 
    {
    TabController controller;
    TextEditingController _email = new TextEditingController();
    TextEditingController _password = new TextEditingController();
    bool loading;

    final GlobalKey < ScaffoldState > _scaffoldKey = new GlobalKey<ScaffoldState>
        ();

    @override
    void initState() {
        // TODO: implement initState
        super.initState();
        _fetchSessionAndNavigate();
        controller = new TabController(length: 2, vsync: this);
        loading = false;
    }

    @override
    void dispose() {
        // TODO: implement dispose
        super.dispose();
        controller.dispose();
        setState(() {
            loading = false;
        });
        _email.dispose();
        _password.dispose();
    }

    final GlobalKey < FormState > _formKey = GlobalKey<FormState>();
    bool _autoValidate = false;

    _login(username, password) async {
        setState(() {
            loading = true;
        });

        var body = json.encode({
            "username": username,
            "password": password,
        });

        Map < String, String > headers = {
            'Content-type': 'application/json',
                'Accept': 'application/json',
      };

        await http
            .post("${GlobalVar.Ip}/wp-json/jwt-auth/v1/token",
                body: body, headers: headers)
            .then((response) {
                var body = json.decode(response.body);
                //var response1;

                if (response.statusCode == 200) {
                    // TODO: you need to store body['token'] to use in some authentication
                    loading = false;
                    Navigator.pushReplacement(context,
                        MaterialPageRoute(builder: (BuildContext ctx) => HomePage()));
    } else {
        // TODO: alert message
        final snackBar = SnackBar(
            content: Text(body['message'].toString().trim()),
        );
        _scaffoldKey.currentState.showSnackBar(snackBar);
    }
    setState(() {
        loading = false;
    });
});
      }

@override
Widget build(BuildContext context) {
    return Scaffold(
        key: _scaffoldKey,
        resizeToAvoidBottomPadding: false,
        body: Container(
            decoration: BoxDecoration(
                image: DecorationImage(
                    image: AssetImage('images/art.png'),
                    fit: BoxFit.fill,
                    colorFilter: ColorFilter.mode(
                        Colors.white12.withOpacity(0.2), BlendMode.dstATop),
                ),
            ),
            child: ListView();
}

Upvotes: 39

Views: 81245

Answers (5)

Faizyy
Faizyy

Reputation: 363

Concession is now deprecated in favour of flutter_session. We can now use flutter_session to manage user sessions seamlessly.

//Write values to the session: 
await FlutterSession().set("token", myJWTToken);

//Read values from the session: 
dynamic token = await FlutterSession().get("token");

Upvotes: 1

Vaibhav Kamani
Vaibhav Kamani

Reputation: 377

The above answers using SharedPreferences works (make sure you have WidgetsFlutterBinding.ensureInitiazed(); as your first line of main), but it will give you a null on re-start, ie, if you remove the app from recent and re-open it again, it will not re-direct you to the Home or Profile Page. I solved this issue by giving write external storage permission to your app because the shared preferences need to write the data somewhere in your device or emulator.

Just add the write and read external storage permissions in your Android Manifest file and you can use permission_handler plugin for flutter from pub.dev to get the required permissions from user at runtime when the app is opened for the first time and then Shared Preferences won't give you null.

Upvotes: 4

Jhourlad Estrella
Jhourlad Estrella

Reputation: 3670

Use user sessions instead. Check out Consession. The package adds user session support in Flutter and is easy to use.

// Store value to session
await Consession().set("token", myJWTToken);

// Retrieve item from session
dynamic token = await Consession().get("token");

Upvotes: 1

Shyju M
Shyju M

Reputation: 9943

You can navigate to the Login page if the user details are saved in the storage else to the Home page with the below code

  Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      SharedPreferences prefs = await SharedPreferences.getInstance();
      var email = prefs.getString('email');
      print(email);
      runApp(MaterialApp(home: email == null ? Login() : Home()));
    }

Save the required user details after the successful login

class Login extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          onPressed: () async {
            //after the login REST api call && response code ==200
            SharedPreferences prefs = await SharedPreferences.getInstance();
            prefs.setString('email', '[email protected]');
            Navigator.pushReplacement(context,
                MaterialPageRoute(builder: (BuildContext ctx) => Home()));
          },
          child: Text('Login'),
        ),
      ),
    );
  }
}

clear the details on logout

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () async {
            SharedPreferences prefs = await SharedPreferences.getInstance();
            prefs.remove('email');
            Navigator.pushReplacement(context,
                MaterialPageRoute(builder: (BuildContext ctx) => Login()));
          },
          child: Text('Logout'),
        ),
      ),
    );
  }
}

Hope it helps!

Upvotes: 98

Wilmer
Wilmer

Reputation: 512

Make sure WidgetFlutterBinding.ensureInitialized() is the first line of main()

import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SharedPreferences prefs = await SharedPreferences.getInstance();
  bool login = prefs.getBool("login");
  print("login:" + login.toString());
  runApp(MaterialApp(home: login == null ? LoginPage(title: 'My App') : HomePage()));
}

class LoginPage extends StatelessWidget { ...

Upvotes: 6

Related Questions