In this Flutter Rest API Integration example we will build user Registration and Authentication with Backend System. Here we are using the Backend Authentication with PHP Registration and Login APIs. In the App side we are maintain the User Authentication status with Shared Preferences. Previous article we have learned REST API Integration in Flutter with Retrofit library and we also updated dependencies with null safety feature. If we have to declare variables before accessing we need to apply late modifier to that variable.
In this example we will design simple flutter login, signup pages along with home page. And we know that showing the snackbar with Scaffold is deprecated so in this flutter login pages we are showing the snackbar with scaffoldMessengerState
Some times we may require to save device details on the server, that data also we can get by flutter device info example
This example contains the below backend PHP files
Front end having the below page
Service Layer This flutter login example will communicate with backend system, so in our application folder create a file api.dart and add server endpoints (API URLS)
We have created a file api.dart file and added all API information
const String ROOT="http://tutionteacher.rrtutors.com"; const String REGISTRATION="$ROOT/api/registration.php"; const String LOGIN="$ROOT/api/login.php"; |
See Create Flutter First Application Here
As usual we need to Create a new Flutter Project
We would need to make HTTP calls and persist data locally, so add two additional packages to pubsec.yaml as well
dev_dependencies: flutter_test: sdk: flutter http: ^0.13.3 flutter_datetime_picker: ^1.5.1 intl: ^0.17.0 webview_flutter: ^2.0.9 shared_preferences: ^2.0.6 |
Then install using flutter pub get
Flutter User Authentication
Here is the code for authentication api integration in flutter
login(email,password) async { Map data = { 'email': email, 'password': password }; print(data.toString()); final response= await http.post( Uri.parse(LOGIN), headers: { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded" }, body: data, encoding: Encoding.getByName("utf-8") ) ; setState(() { isLoading=false; }); if (response.statusCode == 200) { Map<String,dynamic>resposne=jsonDecode(response.body); if(!resposne['error']) { Map<String,dynamic>user=resposne['data']; print(" User name ${user['id']}"); savePref(1,user['name'],user['email'],user['id']); Navigator.pushReplacementNamed(context, "/home"); }else{ print(" ${resposne['message']}"); } scaffoldMessenger.showSnackBar(SnackBar(content:Text("${resposne['message']}"))); } else { scaffoldMessenger.showSnackBar(SnackBar(content:Text("Please try again!"))); } } savePref(int value, String name, String email, int id) async { SharedPreferences preferences = await SharedPreferences.getInstance(); preferences.setInt("value", value); preferences.setString("name", name); preferences.setString("email", email); preferences.setString("id", id.toString()); preferences.commit(); } } |
Map data = { 'email': email, 'password': password }; |
After calling the login api, we are check the response, if the response code received as 200 response.statusCode == 200 then we need to JSON Parse to check the user details
In this we are doing the JSON Parse by jsonDecode method
Map<String,dynamic>response=jsonDecode(response.body); if(!response['error']) { Map<String,dynamic>user=response['data']; print(" User name ${user['id']}"); savePref(1,user['name'],user['email'],user['id']); Navigator.pushReplacementNamed(context, "/home"); } else{ print(" ${resposne['message']}"); } |
User Session management
After login api success response we are saving the user session in Shared Preference. This data we can use it when we start the application. If the session data available we will navigate user directly homescreen
Save User Session:
savePref(int value, String name, String email, int id) async { SharedPreferences preferences = await SharedPreferences.getInstance(); preferences.setInt("value", value); preferences.setString("name", name); preferences.setString("email", email); preferences.setString("id", id.toString()); preferences.commit(); } |
Validate user session:
var _loginStatus=0; getPref() async { SharedPreferences preferences = await SharedPreferences.getInstance(); setState(() { _loginStatus = preferences.getInt("value")!; }); } } |
Create User Account in Database : User Registration
If the user not found in the server, user has to register his account by fill the Registration form, You can find registration form below the article.
Similar to Login api, we will use the registration api integration with below code
signup(name,email,password) async { setState(() { isLoading=true; }); print("Calling"); Map data = { 'email': email, 'password': password, 'name': name }; print(data.toString()); final response= await http.post( Uri.parse(REGISTRATION), headers: { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded" }, body: data, encoding: Encoding.getByName("utf-8") ) ; if (response.statusCode == 200) { setState(() { isLoading=false; }); Map<String,dynamic>resposne=jsonDecode(response.body); if(!resposne['error']) { Map<String,dynamic>user=resposne['data']; print(" User name ${user['data']}"); savePref(1,user['name'],user['email'],user['id']); Navigator.pushReplacementNamed(context, "/home"); }else{ print(" ${resposne['message']}"); } scaffoldMessenger.showSnackBar(SnackBar(content:Text("${resposne['message']}"))); } else { scaffoldMessenger.showSnackBar(SnackBar(content:Text("Please Try again"))); } } |
After successful login we are directly navigating user to Homescreen.
In this Rest API integration we integrated APIs on the main ui, We can do the same functionality with Flutter Bloc Pattern, Flutter Future features.
This Flutter Rest API Integration tutorial need 3 Screen page one for Registration , Login and other for Home screen will show after successful user authenticated.
Now Let's create flutter login page with Validation
Signin.dart
import 'dart:convert'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:rest_app/apis/api.dart'; import 'package:rest_app/screens/signup.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'home.dart'; class SignIn extends StatefulWidget { @override _SignInState createState() => _SignInState(); } class _SignInState extends State<SignIn> { final _formKey = GlobalKey<FormState>(); late String email, password; bool isLoading=false; TextEditingController _emailController=new TextEditingController(); TextEditingController _passwordController=new TextEditingController(); GlobalKey<ScaffoldState>_scaffoldKey=GlobalKey(); late ScaffoldMessengerState scaffoldMessenger ; @override Widget build(BuildContext context) { scaffoldMessenger = ScaffoldMessenger.of(context); return Scaffold( key: _scaffoldKey, body: SingleChildScrollView( child: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: Stack( children: <Widget>[ Container( width: double.infinity, height: double.infinity, child: Image.asset( "assets/background.jpg", fit: BoxFit.fill, ), ), Container( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Center( child: Image.asset( "assets/logo.png", height: 30, width: 30, alignment: Alignment.center, )), SizedBox( height: 13, ), Text( "Learn With Us", style: GoogleFonts.roboto( textStyle: TextStyle( fontSize: 27, color: Colors.white, letterSpacing: 1)), ), SizedBox( height: 5, ), Container( width: 180, child: Text( "RRTutors, Hyderabad", textAlign: TextAlign.center, style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white54, letterSpacing: 0.6, fontSize: 11), ), ), ), SizedBox( height: 40, ), Text( "Sign In", textAlign: TextAlign.center, style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white, letterSpacing: 1, fontSize: 23, ), ), ), SizedBox( height: 8, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( "Learn new Technologies ????", textAlign: TextAlign.center, style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white70, letterSpacing: 1, fontSize: 17, ), ), ), ], ), SizedBox( height: 30, ), Form( key: _formKey, child: Container( margin: EdgeInsets.symmetric(vertical: 10, horizontal: 45), child: Column( children: <Widget>[ TextFormField( style: TextStyle( color: Colors.white, ), controller: _emailController, decoration: InputDecoration( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white)), hintText: "Email", hintStyle: TextStyle( color: Colors.white70, fontSize: 15), ), onSaved: (val) { email = val!; }, ), SizedBox( height: 16, ), TextFormField( style: TextStyle( color: Colors.white, ), controller: _passwordController, decoration: InputDecoration( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white)), hintText: "Password", hintStyle: TextStyle( color: Colors.white70, fontSize: 15), ), onSaved: (val) { email = val!; }, ), SizedBox( height: 30, ), Stack( children: [ GestureDetector( onTap: () { if(isLoading) { return; } if(_emailController.text.isEmpty||_passwordController.text.isEmpty) { scaffoldMessenger.showSnackBar(SnackBar(content:Text("Please Fill all fileds"))); return; } login(_emailController.text,_passwordController.text); setState(() { isLoading=true; }); //Navigator.pushReplacementNamed(context, "/home"); }, child: Container( alignment: Alignment.center, width: double.infinity, padding: EdgeInsets.symmetric( vertical: 10, horizontal: 0), height: 50, decoration: BoxDecoration( border: Border.all(color: Colors.white), borderRadius: BorderRadius.circular(50), ), child: Text( "SUBMIT", textAlign: TextAlign.center, style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white, fontSize: 16, letterSpacing: 1)), ), ), ), Positioned(child: (isLoading)?Center(child: Container(height:26,width: 26,child: CircularProgressIndicator(backgroundColor: Colors.green,))):Container(),right: 30,bottom: 0,top: 0,) ], ) ], ), ), ), SizedBox( height: 20, ), Text( "OR", style: TextStyle(fontSize: 14, color: Colors.white60), ), SizedBox( height: 20, ), Image.asset( "assets/fingerprint.png", height: 36, width: 36, ), SizedBox( height: 30, ), GestureDetector( onTap: () { Navigator.pushReplacementNamed(context, "/signup"); }, child: Text( "Don't have an account?", style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white70, fontSize: 13, decoration: TextDecoration.underline, letterSpacing: 0.5)), ), ) ], ), ), ], ), ), )); } login(email,password) async { Map data = { 'email': email, 'password': password }; print(data.toString()); final response= await http.post( Uri.parse(LOGIN), headers: { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded" }, body: data, encoding: Encoding.getByName("utf-8") ) ; setState(() { isLoading=false; }); if (response.statusCode == 200) { Map<String,dynamic>resposne=jsonDecode(response.body); if(!resposne['error']) { Map<String,dynamic>user=resposne['data']; print(" User name ${user['id']}"); savePref(1,user['name'],user['email'],user['id']); Navigator.pushReplacementNamed(context, "/home"); }else{ print(" ${resposne['message']}"); } scaffoldMessenger.showSnackBar(SnackBar(content:Text("${resposne['message']}"))); } else { scaffoldMessenger.showSnackBar(SnackBar(content:Text("Please try again!"))); } } savePref(int value, String name, String email, int id) async { SharedPreferences preferences = await SharedPreferences.getInstance(); preferences.setInt("value", value); preferences.setString("name", name); preferences.setString("email", email); preferences.setString("id", id.toString()); preferences.commit(); } } |
Read here how to Add placeholder text to Textfield or TextFormfield in flutter
The above code will generate Login Page Like below
signup.dart
import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:rest_app/apis/api.dart'; import 'package:rest_app/screens/signin.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'home.dart'; class SignUp extends StatefulWidget { @override _SignUpState createState() => _SignUpState(); } class _SignUpState extends State<SignUp> { final _formKey = GlobalKey<FormState>(); late String name,email, password; bool isLoading=false; GlobalKey<ScaffoldState>_scaffoldKey=GlobalKey(); late ScaffoldMessengerState scaffoldMessenger ; var reg=RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+"); TextEditingController _nameController=new TextEditingController(); TextEditingController _emailController=new TextEditingController(); TextEditingController _passwordController=new TextEditingController(); @override Widget build(BuildContext context) { scaffoldMessenger = ScaffoldMessenger.of(context); return Scaffold( key: _scaffoldKey, body: SingleChildScrollView( child: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: Stack( children: <Widget>[ Container( width: double.infinity, height: double.infinity, child: Image.asset( "assets/background.jpg", fit: BoxFit.fill, ), ), Container( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Center( child: Image.asset( "assets/logo.png", height: 30, width: 30, alignment: Alignment.center, )), SizedBox( height: 13, ), Text( "Learn With Us", style: GoogleFonts.roboto( textStyle: TextStyle( fontSize: 27, color: Colors.white, letterSpacing: 1)), ), SizedBox( height: 5, ), Container( width: 180, child: Text( "RRTutors, Hyderabad", textAlign: TextAlign.center, style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white54, letterSpacing: 0.6, fontSize: 11), ), ), ), SizedBox( height: 20, ), Text( "Sign Up", textAlign: TextAlign.center, style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white, letterSpacing: 1, fontSize: 23, ), ), ), SizedBox( height: 8, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( "Learn new Technologies ????", textAlign: TextAlign.center, style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white70, letterSpacing: 1, fontSize: 17, ), ), ), ], ), SizedBox( height: 30, ), Form( key: _formKey, child: Container( margin: EdgeInsets.symmetric(vertical: 10, horizontal: 45), child: Column( children: <Widget>[ TextFormField( style: TextStyle( color: Colors.white, ), controller: _nameController, decoration: InputDecoration( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white)), hintText: "Name", hintStyle: TextStyle( color: Colors.white70, fontSize: 15), ), onSaved: (val) { name = val!; }, ), SizedBox( height: 16, ), TextFormField( style: TextStyle( color: Colors.white, ), controller: _emailController, decoration: InputDecoration( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white)), hintText: "Email", hintStyle: TextStyle( color: Colors.white70, fontSize: 15), ), onSaved: (val) { email = val!; }, ), SizedBox( height: 16, ), TextFormField( style: TextStyle( color: Colors.white, ), controller: _passwordController, decoration: InputDecoration( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white)), hintText: "Password", hintStyle: TextStyle( color: Colors.white70, fontSize: 15), ), onSaved: (val) { password = val!; }, ), SizedBox( height: 30, ), Stack( children: [ Container( alignment: Alignment.center, width: double.infinity, padding: EdgeInsets.symmetric( vertical: 10, horizontal: 0), height: 50, decoration: BoxDecoration( border: Border.all(color: Colors.white), borderRadius: BorderRadius.circular(50), ), child: InkWell( onTap: (){ if(isLoading) { return; } if(_nameController.text.isEmpty) { scaffoldMessenger.showSnackBar(SnackBar(content:Text("Please Enter Name"))); return; } if(!reg.hasMatch(_emailController.text)) { scaffoldMessenger.showSnackBar(SnackBar(content:Text("Enter Valid Email"))); return; } if(_passwordController.text.isEmpty||_passwordController.text.length<6) { scaffoldMessenger.showSnackBar(SnackBar(content:Text("Password should be min 6 characters"))); return; } signup(_nameController.text,_emailController.text,_passwordController.text); }, child: Text( "CREATE ACCOUNT", textAlign: TextAlign.center, style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white, fontSize: 16, letterSpacing: 1)), ), ), ), Positioned(child: (isLoading)?Center(child: Container(height:26,width: 26,child: CircularProgressIndicator(backgroundColor: Colors.green,))):Container(),right: 30,bottom: 0,top: 0,) ], ) ], ), ), ), SizedBox( height: 20, ), GestureDetector( onTap: () { Navigator.pushReplacementNamed(context, "/signin"); }, child: Text( "Already have an account?", style: GoogleFonts.roboto( textStyle: TextStyle( color: Colors.white70, fontSize: 13, decoration: TextDecoration.underline, letterSpacing: 0.5)), ), ) ], ), ), ], ), ), )); } signup(name,email,password) async { setState(() { isLoading=true; }); print("Calling"); Map data = { 'email': email, 'password': password, 'name': name }; print(data.toString()); final response= await http.post( Uri.parse(REGISTRATION), headers: { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded" }, body: data, encoding: Encoding.getByName("utf-8") ) ; if (response.statusCode == 200) { setState(() { isLoading=false; }); Map<String,dynamic>resposne=jsonDecode(response.body); if(!resposne['error']) { Map<String,dynamic>user=resposne['data']; print(" User name ${user['data']}"); savePref(1,user['name'],user['email'],user['id']); Navigator.pushReplacementNamed(context, "/home"); }else{ print(" ${resposne['message']}"); } scaffoldMessenger.showSnackBar(SnackBar(content:Text("${resposne['message']}"))); } else { scaffoldMessenger.showSnackBar(SnackBar(content:Text("Please Try again"))); } } savePref(int value, String name, String email, int id) async { SharedPreferences preferences = await SharedPreferences.getInstance(); preferences.setInt("value", value); preferences.setString("name", name); preferences.setString("email", email); preferences.setString("id", id.toString()); preferences.commit(); } } |
The above code will generate Below Registration UI
How to make email validation in flutter?
In this REST API integration email validation is made by using Reg expression like below, we can also validate form fields by using Flutter Form Builder
var reg=RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+"); reg.hasMatch(_emailController.text) |
In both the Registration and Login pages we have Flutter TextField and an material button, when clicked perform an Registration or Login task
home.dart
import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:webview_flutter/webview_flutter.dart'; class Home extends StatefulWidget { @override _HomeState createState() => _HomeState(); } class _HomeState extends State { bool isLoading=false; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black54, appBar: AppBar( leading: InkWell(child: Icon(Icons.compare_arrows),onTap: () async { SharedPreferences preferences = await SharedPreferences.getInstance(); preferences.clear(); Navigator.pushReplacementNamed(context, "/login"); },), title: Text( "Lear With Us", style: GoogleFonts.roboto( textStyle: TextStyle(fontSize: 18, letterSpacing: 1)), ), backgroundColor: Colors.black87, centerTitle: true, actions: [ ], ), body: Stack( children: [ WebView( javascriptMode: JavascriptMode.unrestricted, initialUrl: 'https://rrtutors.com/language/Flutter', onPageFinished:(value){ setState(() { isLoading=true; }); }, ), (!isLoading)?Center( child: CircularProgressIndicator( backgroundColor: Colors.green, ), ):Container() ], ), ); } } |
main.dart
import 'package:flutter/material.dart'; import 'package:rest_app/screens/home.dart'; import 'package:rest_app/screens/signin.dart'; import 'package:rest_app/screens/signup.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() { runApp(MaterialApp(home: MyApp(),)); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override void initState() { // TODO: implement initState super.initState(); getPref(); } @override Widget build(BuildContext context) { return MaterialApp( home: Stack(children: [ Container( width: double.infinity, height: double.infinity, child: Image.asset( "assets/background.jpg", fit: BoxFit.fill, ), ), (_loginStatus==1)?Home():SignIn() ],), theme: ThemeData.light(), debugShowCheckedModeBanner: false, routes: <String, WidgetBuilder>{ '/signin': (BuildContext context) => new SignIn(), '/signup': (BuildContext context) => new SignUp(), '/home': (BuildContext context) => new Home(), }, ); } var _loginStatus=0; getPref() async { SharedPreferences preferences = await SharedPreferences.getInstance(); setState(() { _loginStatus = preferences.getInt("value")!; }); } } |
Conclusion: In this flutter rest api integration example we covered how to design flutter login, registration(signup page) pages and authenticate user with backend php rest apis.
Tags: Flutter Rest API, User Login page with Validation, Flutter Registration page, Rest Api integration, Flutter login, signup pages
Flutter Examples
Flutter Beginner Project - Break Timer
Flutter LinearProgressIndicator - Show Download Progress
Article Contributed By :
|
|
|
|
49228 Views |