Flutter: Keep user logged in after app closes and reopen - authentication

I'm a beginner and requesting help. I tried to find the answer but sadly cannot find the answer that I'm looking for. I'm building an app where users can see the homepage and other parts of the app when they are not logged in. This part I have working but only when I close the app and restart it I need to log in again. This is of course not ideal. I tried to look for the SharedPreferences but all examples I can find are with a login function for the whole app and I can't figure out how to get it working in my app. Below is the code I have so far. All help is appreciated and thank you all in advance!
(Apologies for posting so much code but it might help!)
Main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:reboo1/services/firebaseauthservice.dart';
import 'package:reboo1/services/users.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: MaterialApp(
title: 'Rèboo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home:HomePage(),
),
);
}
}
HomePage.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:reboo1/authenticate/signin.dart';
import 'package:reboo1/authenticate/signout.dart';
import 'package:reboo1/models/drawerlogin.dart';
import 'package:reboo1/models/drawerlogout.dart';
import 'package:reboo1/services/firebaseauthservice.dart';
import 'package:reboo1/services/users.dart';
class DrawerItem {
String title;
IconData icon;
DrawerItem(this.title, this.icon);
}
class HomePage extends StatefulWidget {
final drawerItems = [
new DrawerItem("Rèboo", Icons.home),
new DrawerItem("Inbox", Icons.mail_outline),
new DrawerItem("Profile", Icons.person_outline),
new DrawerItem("Reservations", Icons.event_note),
new DrawerItem("Favorites", Icons.favorite_border),
new DrawerItem("Vouchers", Icons.card_giftcard),
new DrawerItem("Invite Friends", Icons.person_add),
new DrawerItem("Settings", Icons.settings),
new DrawerItem("FAQ", Icons.help_outline),
new DrawerItem("Terms & Conditions", Icons.assignment),
new DrawerItem("Sign out", Icons.exit_to_app),
];
#override
State<StatefulWidget> createState() {
return new HomePageState();
}
}
class HomePageState extends State<HomePage> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
int _selectedDrawerIndex = 0;
var _setIcon = Icons.person;
var drawer;
String uid;
_getDrawerItemWidget(int pos) {
switch (pos) {
case 0:
return new Reboo();
case 1:
return new Inbox();
case 2:
return new Profile();
case 3:
return new Reservations();
case 4:
return new Favorites();
case 5:
return new Vouchers();
case 6:
return new InviteFriends();
case 7:
return new Settings();
case 8:
return new Faq();
case 9:
return new TermsAndConditions();
case 10:
return new SignOut();
default:
return new Text("Error");
}
}
_onSelectItem(int index) {
setState(() => _selectedDrawerIndex = index);
if (_selectedDrawerIndex == 0) {
setState(() => _setIcon = Icons.person);
} else {
setState(() => _setIcon = Icons.arrow_back);
}
Navigator.of(context).pop(); // close the drawer
}
#override
Widget build(BuildContext context) {
var drawerOptions = <Widget>[];
for (var i = 0; i < widget.drawerItems.length; i++) {
var d = widget.drawerItems[i];
drawerOptions.add(new ListTile(
leading: new Icon(
d.icon,
color: Color(0xFF008577),
),
title: new Text(d.title),
selected: i == _selectedDrawerIndex,
onTap: () => _onSelectItem(i),
));
}
final auth = Provider.of<User>(context, listen: false);
if (auth != null) {
drawer = DrawerLogin();
} else {
drawer = DrawerLogout();
}
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
leading: Builder(
builder: (BuildContext context) {
return IconButton(
icon: new Icon(_setIcon),
onPressed: () {
if (_selectedDrawerIndex == 0) {
Scaffold.of(context).openDrawer();
} else {
setState(() => _selectedDrawerIndex = 0);
setState(() => _setIcon = Icons.person);
}
},
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
);
},
),
centerTitle: true,
title: new Text(widget.drawerItems[_selectedDrawerIndex].title),
backgroundColor: Color(0xFF008577),
elevation: 0.0,
actions: <Widget>[
IconButton(
icon: Icon(Icons.menu, color: Colors.white),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Company()),
);
},
)
],
),
drawer: new Drawer(
child: SingleChildScrollView(
child: new Column(
children: <Widget>[drawer, new Column(children: drawerOptions)],
),
),
),
body: _getDrawerItemWidget(_selectedDrawerIndex),
);
}
}
FirebaseAuthService.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:reboo1/services/users.dart';
import 'package:reboo1/services/database.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// create user obj based on FirebaseUser
User _userFromFirebaseUser(FirebaseUser user){
return user != null ? User(uid: user.uid) : null;
}
// auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged
.map(_userFromFirebaseUser);
}
// sign with email & password
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
}catch(e){
print(e.toString());
return null;
}
}
// register with email & password
Future registerForm(String email, String password, String birthday, String address, String fullName, String phone) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
// creat a new document in the database for the user with the uid
await DatabaseService(uid: user.uid).updateUserData(email, birthday, address, fullName, phone);
return _userFromFirebaseUser(user);
}catch(e){
print(e.toString());
return null;
}
}
Stream<String> get onAuthStateChanged =>
_auth.onAuthStateChanged.map(
(FirebaseUser user) => user?.uid,
);
// GET UID
Future<String> getCurrentUID() async {
return (await _auth.currentUser()).uid;
}
Future getCurrentUser() async {
return await _auth.currentUser();
}
//sign out
Future signOut() async{
try{
return await _auth.signOut();
}catch(e){
print(e.toString());
return null;
}
}
}
SignIn.dart
import 'package:flutter/material.dart';
import 'package:reboo1/authenticate/register.dart';
import 'package:reboo1/home/homepage.dart';
import 'package:reboo1/services/constants.dart';
import 'package:reboo1/services/loading.dart';
import 'package:reboo1/services/firebaseauthservice.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SignIn extends StatefulWidget {
final Function toggleView;
SignIn({this.toggleView});
#override
_SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> {
final AuthService _auth = AuthService();
final _formKey = GlobalKey<FormState>(); //global key
bool loading = false;
// text field state
String email = '';
String password = '';
String error = '';
#override
Widget build(BuildContext context) {
return loading
? Loading()
: Scaffold(
backgroundColor: Colors.brown[50],
appBar: AppBar(
backgroundColor: Color(0xFF008577),
elevation: 0.0,
title: Text('Sign in to Rèboo'),
actions: <Widget>[
FlatButton.icon(
textColor: Colors.white,
icon: Icon(Icons.person),
label: Text('Register'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Register()),
);
},
)
],
),
body: Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 50.0),
child: Form(
key: _formKey, //global key
child: Column(children: <Widget>[
SizedBox(height: 20.0),
TextFormField(
decoration: textInputDecoration.copyWith(
hintText: 'Email address'),
validator: (val) =>
val.isEmpty ? 'Enter an email address' : null,
onChanged: (val) {
setState(() => email = val);
}),
SizedBox(height: 20.0),
TextFormField(
decoration:
textInputDecoration.copyWith(hintText: 'Password'),
validator: (val) =>
val.length < 8 ? 'Enter valid password' : null,
obscureText: true,
onChanged: (val) {
setState(() => password = val);
},
),
SizedBox(height: 20.0),
RaisedButton(
color: Colors.purple[400],
child:
Text('Sign in', style: TextStyle(color: Colors.white)),
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() => loading = true);
dynamic result = await _auth.signInWithEmailAndPassword(
email, password);
if (result == null) {
setState(() {
error =
'Could not sign in with those credentials. Please register an account.';
setState(() => loading = false);
});
} else {
setState(() => loading = false);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
}
}
},
),
SizedBox(height: 12.0),
Text(
error,
style: TextStyle(color: Colors.red, fontSize: 14.0),
)
]),
),
),
);
}
}

Have provided a dummy implementation but this is the legit way to tackle this. If you want to search on google, search for keyword firebase onAuthChanged, and read about it. No local storage is required and the most simple and secure way to handle your requirement.
StreamBuilder<FirebaseUser>(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return print("getting data");
} else if (snapshot.connectionState == ConnectionState.active &&
!snapshot.hasData) {
return print("no user found");
} else if (snapshot.connectionState == ConnectionState.active &&
snapshot.hasData)
{
return print(snapshot.data.currentuser);
}
else
return null;
},

You could save some sort of data to your shared preferences, then when a user opens the app you could retrieve that data from the shared preferences to determine if the user should already be logged in or not. That data could be the users bearer token and expiry date for instance. This could look something like this:
Save data to shared preferences:
Future storeTokenPropertiesToPreferences(
TokenProperties accessTokenProperties, refreshTokenProperties) async {
final preferences = await SharedPreferences.getInstance();
preferences.setString(
_preferencesLocation,
json.encode(
{
'accessToken': accessTokenProperties?.value,
'refreshToken': refreshTokenProperties?.value,
'accessTokenExpiresAt':
accessTokenProperties?.expiresAt?.toIso8601String(),
'refreshTokenExpiresAt':
refreshTokenProperties?.expiresAt?.toIso8601String(),
},
),
);
Retrieve data:
Future<TokenProperties> _tokenPropertiesFromPreferences(
String tokenName) async {
final _userData = await _getPreferences();
try {
final value = _userData[tokenName];
final expiresAt = DateTime.parse(_userData['${tokenName}ExpiresAt']);
final lifeTime = expiresAt.difference(DateTime.now()).inSeconds;
return (value == null || expiresAt == null)
? null
: TokenProperties(value, lifeTime);
} catch (e) {
await _loggingService.log(LoggingMethod.ERROR,
'Could not get token properties from preferences for token $tokenName. Got exception: $e');
return null;
}
Future<Map<String, Object>> _getPreferences() async {
final preferences = await SharedPreferences.getInstance();
if (!preferences.containsKey(_preferencesLocation)) return null;
return json.decode(preferences.getString(_preferencesLocation))
as Map<String, Object>;
}
You could obviously change out the object properties to whatever you need, this is just an example.

I don't think you need to mess up with local storage to save user's detail.As Firebase itself store user's detail in local storage.You just need to call .currentUser() method of FirebaseAuth class object when your app starts. If the current user is null then load Login Page otherwise your Main Page. Just like that;
Future loadUser() async {
FirebaseUser _tempUser = await _auth.currentUser();
if (_tempUser != null)
// goto MainPage(mainUser:_tempUser);
} else
// goto LoginPage;
}

thanks to #UTKARSH Sharma I found out that the user is not logged out but the problem was in my own code. I found the below code which helped me solve my problem:
#override
void initState() {
super.initState();
var auth = FirebaseAuth.instance;
auth.onAuthStateChanged.listen((user) {
if (user != null) {
print("user is logged in");
//navigate to home page using Navigator Widget
} else {
print("user is not logged in");
//navigate to sign in page using Navigator Widget
}
});
}
Thank you everyone for your help!

Related

how to upload multiple multipart images through API in flutter

I am new to app development & still learning flutter, I used multiple image picker package to pick multiple images from gallery, I am wondering how can I post the list of images to to server using API? I am using MongoDB with AWS. any help is appreciated.
Future<String> uploadImage(filename) async {
var request = http.MultipartRequest('POST', Uri.parse(serverReceiverPath));
request.files.add(await http.MultipartFile.fromPath('file', filename));
var res = await request.send();
print(res.statusCode);
var bodyResponse = await res.stream.bytesToString(); // response body
print(bodyResponse);
}
Below is code to pick images from gallery using multi image picker, I am able to pick images and show them on the screen.
class PickImages extends StatefulWidget {
#override
_PickImagesState createState() => _PickImagesState();
}
class _PickImagesState extends State<PickImages> {
List<Asset> images = List<Asset>();
// String _error = 'No Error Detected';
#override
void initState() {
super.initState();
}
Widget buildGridView() {
return GridView.count(
crossAxisCount: 3,
children: List.generate(images.length, (index) {
Asset asset = images[index];
return AssetThumb(
asset: asset,
width: 300,
height: 300,
);
}),
);
}
Future<void> loadAssets() async {
List<Asset> resultList = List<Asset>();
String error = 'No Error Dectected';
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 300,
enableCamera: true,
selectedAssets: images,
cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
materialOptions: MaterialOptions(
actionBarColor: "#abcdef",
actionBarTitle: "Example App",
allViewTitle: "All Photos",
useDetailsView: false,
selectCircleStrokeColor: "#000000",
),
);
} on Exception catch (e) {
error = e.toString();
}
if (!mounted) return;
setState(() {
images = resultList;
// _error = error;
});
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
height: height(context)*0.35,
width: 400,
child: buildGridView()),
RaisedButton(
child: Text("Pick images"),
onPressed: loadAssets,
),
],
);
}
}

Flutter : Why is my builder not getting reloaded after web service call?

I have written the web service call and is being called in the initState() method. A CircularProgressIndicator() is being called if there is no data available. But the progress indicator keeps on rotating even though the web service call is over!
After making a service call, why is my builder not getting reloaded?
I am new to flutter!! Am I going wrong anywhere?
class _DashboardState extends State<Dashboard> {
bool isLoading = false;
Future<List<OrganizationModel>> fetchOrganizationData() async {
isLoading = true;
var response = await http.get(organizationAPI);
if (response.statusCode == 200) {
final items = json.decode(response.body).cast<Map<String, dynamic>>();
orgModelList = items.map<OrganizationModel>((json) {
return OrganizationModel.fromJson(json);
}).toList();
isLoading = false;
return orgModelList;
} else {
isLoading = false;
throw Exception('Failed to load internet');
}
}
#override
void initState() {
this.fetchOrganizationData();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dashboard"),
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xFF076A72), Color(0xFF64B672)])),
child: Column(
children: <Widget>[
Container(
color: Color(0xFF34A086),
height: 1,
),
isLoading ? loadProgressIndicator() : Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 40, right: 40),
child: ListView(children: <Widget>[])
---my code goes here---
you must call setState(() => isLoading = false;) so Flutter can update the state of the view, and in doing so It will hide your CircularProgressIndicator.
Exception('Failed to load internet'); <-
not a good idea since you'r calling the fetchOrganizationData() without a try catch block
It would be better to try something like :
class _DashboardState extends State<Dashboard> {
bool isLoading = false;
bool isFailure = false;
List<OrganizationModel> orgModelList; // this was missing
//since your not using the return value ( it's saved in the state directly ) you could not set the return type
fetchOrganizationData() async {
isLoading = true;
isFailure = false;
var response = await http.get(organizationAPI);
if (response.statusCode == 200) {
final items = json.decode(response.body).cast<Map<String, dynamic>>();
orgModelList = items.map<OrganizationModel>((json) {
return OrganizationModel.fromJson(json);
}).toList();
isFailure = false;
// the return is not required
} else {
isFailure = true;
}
isLoading = false;
setState((){}); // by calling this after the whole state been set, you reduce some code lines
//setState is required to tell flutter to rebuild this widget
}
This way you have a isFailure flag saying if something went wrong while fetching.

Flutter API Resulting In Null

currently working on a flutter project with API. I'm quite new to flutter,
My Code:
Results null.
Being working on it for quite some time but couldn't find a solution. First, try on a flutter app therefore I'm quite new to this, would appreciate any solutions or tips/resources.
All variables are resulting in null as you can see I tried printing them couldn't figure out why.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
void main() => runApp(MyApp());
Future<Data> getData() async {
final response = await get("https://covid-api.com/api/reports?date=2020-03-25&iso=TUR&region_name=Turkey");
if(response.statusCode == 200) {
return Data.fromJson(jsonDecode(response.body));
} else {
throw Exception('Not Working');
}
}
class Data {
String date;
int confirmed;
int deaths;
int recovered;
int confirmedDiff;
int deathsDiff;
int recoveredDiff;
int active;
int activeDiff;
double fatalityRate;
Data({
this.date,
this.confirmed,
this.deaths,
this.recovered,
this.confirmedDiff,
this.deathsDiff,
this.recoveredDiff,
this.active,
this.activeDiff,
this.fatalityRate,
});
factory Data.fromJson(Map<String, dynamic> json) {
return Data(
confirmed: json['confirmed'],
deaths: json['deaths'],
recovered: json['recovered'],
confirmedDiff: json['confirmed_diff'],
deathsDiff: json['deaths_diff'],
recoveredDiff: json['recovered_diff'],
active: json['active'],
activeDiff: json['active_diff'],
fatalityRate: json['fatality_rate'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['date'] = this.date;
data['confirmed'] = this.confirmed;
data['deaths'] = this.deaths;
data['recovered'] = this.recovered;
data['confirmed_diff'] = this.confirmedDiff;
data['deaths_diff'] = this.deathsDiff;
data['recovered_diff'] = this.recoveredDiff;
data['active'] = this.active;
data['active_diff'] = this.activeDiff;
data['fatality_rate'] = this.fatalityRate;
return data;
}
}
class MyApp extends StatelessWidget {
final Future<Data> data = getData();
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primaryColor: Colors.red),
home: Scaffold(
appBar: AppBar(title: Text('COVID-19 Turkey')),
body: Center(
child: FutureBuilder<Data>(
future: data,
builder: (context, snapshot) {
print(snapshot.data.deaths);
print('wtf');
print(snapshot.data.deathsDiff);
print(snapshot.data.recovered);
if(snapshot.hasData){
return Text(snapshot.data.confirmed.toString());
} else if (snapshot.hasError) {
return Text('Error');
}
return Center(child: CircularProgressIndicator(),);
},
),)
)
);
}
}
I think the following is the right way of using FutureBuilder:
FutureBuilder(
future: getData(),
builder: (context, snapshot) {
if (!snapshot.hasData
&& snapshot.connectionState != ConnectionState.done) {
return Center(child: CircularProgressIndicator());
}
if(snapshot.hasData) {
return Text(snapshot.data.confirmed.toString());
} else if (snapshot.hasError) {
return Text('Error');
}
});
Hope it helps!
The problem is in your JSON parsing. On this line,
return Data.fromJson(jsonDecode(response.body));
I called your API and it is giving a Map in which there is a data field and then there is a list of objects in it.
Your getData function needs to be like this,
Future<Data> getData() async {
final response = await get("https://covid-api.com/api/reports?date=2020-03-25&iso=TUR&region_name=Turkey");
if(response.statusCode == 200) {
var data = jsonDecode(response.body);
var firstObj = (data['data'] as List<dynamic>).first;
return Data.fromJson(firstObj);
} else {
throw Exception('Not Working');
}
}
Hope this fixes it for you.

Issue loading assets into flutter project

I'm trying to load a TFLite model into flutter but I'm getting the exception "failed to load model". I've loaded the asset through the yaml, imported the TFLite plugin and made sure the file path is right but I keep getting the same exception printed. I've tested the model with python and it works so I'm just trying to get it to work with flutter now.
Code:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tflite/tflite.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image/image.dart' as img;
void main() {
runApp(MyApp());
}
const String TF = "image_classifier";
//const String yolo = "Tiny YOLOv2";
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: TfliteHome(),
);
}
}
class TfliteHome extends StatefulWidget {
#override
_TfliteHomeState createState() => _TfliteHomeState();
}
class _TfliteHomeState extends State<TfliteHome> {
String _model = TF;
File _image;
double _imageWidth;
double _imageHeight;
bool _busy = false;
List _recognitions;
#override
void initState() {
super.initState();
_busy = true;
loadModel().then((val) {
setState(() {
_busy = false;
});
});
}
loadModel() async {
Tflite.close();
try {
String res;
res = await Tflite.loadModel(
model: "assets/image_classifier.tflite",
labels: "assets/image_labels.txt",
);
print(res);
} on PlatformException {
print("Failed to load the model");
}
}
selectFromImagePicker() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
if (image == null) return;
setState(() {
_busy = true;
});
predictImage(image);
}
predictImage(File image) async {
if (image == null) return;
if (_model == TF) {
await TFModel(image);
}
FileImage(image)
.resolve(ImageConfiguration())
.addListener((ImageStreamListener((ImageInfo info, bool _) {
setState(() {
_imageWidth = info.image.width.toDouble();
_imageHeight = info.image.height.toDouble();
});
})));
setState(() {
_image = image;
_busy = false;
});
}
TFModel(File image) async {
var recognitions = await Tflite.detectObjectOnImage(
path: image.path,
model: "image_classifier",
threshold: 0.3,
imageMean: 0.0,
imageStd: 255.0,
numResultsPerClass: 3);
setState(() {
_recognitions = recognitions;
});
}
List<Widget> renderBoxes(Size screen) {
if (_recognitions == null) return [];
if (_imageWidth == null || _imageHeight == null) return [];
double factorX = screen.width;
double factorY = _imageHeight / _imageHeight * screen.width;
Color blue = Colors.red;
return _recognitions.map((re) {
return Positioned(
left: re["rect"]["x"] * factorX,
top: re["rect"]["y"] * factorY,
width: re["rect"]["w"] * factorX,
height: re["rect"]["h"] * factorY,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: blue,
width: 3,
)),
child: Text(
"${re["detectedClass"]} ${(re["confidenceInClass"] * 100).toStringAsFixed(0)}%",
style: TextStyle(
background: Paint()..color = blue,
color: Colors.white,
fontSize: 15,
),
),
),
);
}).toList();
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
List<Widget> stackChildren = [];
stackChildren.add(Positioned(
top: 0.0,
left: 0.0,
width: size.width,
child: _image == null ? Text("No Image Selected") : Image.file(_image),
));
stackChildren.addAll(renderBoxes(size));
if (_busy) {
stackChildren.add(Center(
child: CircularProgressIndicator(),
));
}
return Scaffold(
appBar: AppBar(
title: Text("TFLite Demo"),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.image),
tooltip: "Pick Image from gallery",
onPressed: selectFromImagePicker,
),
body: Stack(
children: stackChildren,
),
);
}
}
Pubspec.yaml:
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- assets/image_classifier.tflite
- assets/image_labels.txt
File Path:
Android
In android/app/build.gradle, add the following setting in android block.
aaptOptions {
noCompress 'tflite'
noCompress 'lite'
}
worked for me!!
I think:
assets:
- assets/image_classifier.tflite // also not the two-space indentation
- assets/image_labels.txt
should be without the 'assets' in the paths.
assets:
- image_classifier.tflite
- image_labels.txt

How to make a basic http auth ( Login and Register ) and store the token

how are you ?
i have laravel backend with passport auth and now i want to link it with my mobile app in flutter
i want to make the auth but i'm new in flutter and i don't know how to start to do this
first i make my models
this is my first model login.dart
class Login {
final String login;
final String password;
Login (this.login,this.password);
}
my second model is register.dart
class Register {
final String email;
final String name;
final String mobile;
final String password;
Register(
this.email,
this.name,
this.mobile,
this.password,
);
}
and this is User model
class User {
final int id ;
final int active ;
final int confirmed ;
final String mobile ;
final String name ;
final String email ;
final String confirmation_code ;
User(this.id,this.active,this.confirmed,this.mobile,this.name,this.email,this.confirmation_code);
}
this is my Auth Response Model
import './User.dart';
class AuthResponse {
final String token;
final User user;
AuthResponse(
this.user, this.token
);
}
but now i don't know how to make the auth and link it with these models so can any one help please
thanks
New codes
my login page code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/services.dart';
import '../../common/apifunctions/requestLoginAPI.dart';
import 'package:gradient_widgets/gradient_widgets.dart';
class UserLoginPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _UserLoginPage();
}
}
class _UserLoginPage extends State<UserLoginPage> {
final TextEditingController _mobileController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
#override
void initState() {
super.initState();
_saveCurrentRoute('/UserLogin');
}
_saveCurrentRoute(String lastRoute) async {
SharedPreferences preferences = await SharedPreferences.getInstance();
await preferences.setString('LastScreenRoute', lastRoute);
}
void _gloginButton() {
Navigator.pushReplacementNamed(context, '/Home');
}
void _registerButton() {
Navigator.pushNamed(context, '/UserRegister');
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
if (Navigator.canPop(context)) {
Navigator.of(context).pushNamedAndRemoveUntil(
'/Home', (Route<dynamic> route) => false);
} else {
Navigator.of(context).pushReplacementNamed('/Home');
}
},
child: Scaffold(
body: Column(
children: <Widget>[
Image.asset('assets/img/LRUI.png'),
Form(
child: Container(
//padding: EdgeInsets.only(top: 100.0),
margin: EdgeInsets.all(35.0),
child: Center(
child: Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(
height: 99.0,
),
TextFormField(
controller: _mobileController,
decoration: InputDecoration(
labelText: 'رقم الجوال',
hintText: "رقم الجوال يجب أن يكون عشر ارقام",
),
style: TextStyle(
fontSize: 18.0,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 11.0),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(
labelText: 'الرقم السري',
),
obscureText: true,
style: TextStyle(
fontSize: 18.0,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 40.0,
),
GradientButton(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomCenter,
colors: const <Color>[
Color(0xff4caf4e),
Color(0xff71c071),
],
),
callback: () {
SystemChannels.textInput
.invokeMethod('TextInput.hide');
requestLoginAPI(context, _mobileController.text,
_passwordController.text);
},
textStyle: TextStyle(
color: Colors.white, fontSize: 16.0),
shapeRadius: BorderRadius.circular(10.0),
child: Text(
"دخول",
),
increaseHeightBy: 20.0,
increaseWidthBy: 140.0,
),
SizedBox(
height: 35.0,
),
FlatButton(
child: Text('دخول كضيف'),
onPressed: _gloginButton,
),
FlatButton(
child: Text('تسجيل حساب جديد'),
onPressed: _registerButton,
),
],
),
),
),
),
),
),
],
),
));
}
}
and this is my my Api function code for request login
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../functions/ saveCurrentLogin.dart';
import '../functions/showDialog.dart';
import 'dart:convert';
import '../../Models/Login.dart';
import '../../Models/User.dart';
import '../../Models/AuthResponse.dart';
Future<Login> requestLoginAPI(BuildContext context, String login, String password) async {
final url = "http://188.166.172.146/Blooming/public/api/login";
Map<String, String> body = {
'login': login,
'password': password,
};
final response = await http.post(
url,
body: body,
);
if (response.statusCode == 200) {
final responseJson = json.decode(response.body);
var token = new AuthResponse.fromJson(responseJson);
saveCurrentLogin(responseJson);
Navigator.of(context).pushReplacementNamed('/About');
return Login.fromJson(responseJson);
} else {
final responseJson = json.decode(response.body);
saveCurrentLogin(responseJson);
showDialogSingleButton(context, "خطأ", "تأكد من معلومات الدخول", "موافق");
return null;
}
}
this is my save current login function code
import 'package:shared_preferences/shared_preferences.dart';
import '../../Models/AuthResponse.dart';
import '../../Models/User.dart';
saveCurrentLogin(Map responseJson) async {
SharedPreferences preferences = await SharedPreferences.getInstance();
var token = (responseJson != null && !responseJson.isEmpty) ? AuthResponse.fromJson(responseJson).token : "";
var id = (responseJson != null && !responseJson.isEmpty) ? User.fromJson(responseJson).id : 0;
var name = (responseJson != null && !responseJson.isEmpty) ? User.fromJson(responseJson).name : "";
var email = (responseJson != null && !responseJson.isEmpty) ? User.fromJson(responseJson).email : "";
var mobile = (responseJson != null && !responseJson.isEmpty) ? User.fromJson(responseJson).mobile : "";
var active = (responseJson != null && !responseJson.isEmpty) ? User.fromJson(responseJson).active : 0;
var confirmation_code = (responseJson != null && !responseJson.isEmpty) ? User.fromJson(responseJson).confirmation_code : "";
var confirmed = (responseJson != null && !responseJson.isEmpty) ? User.fromJson(responseJson).confirmed : 0;
await preferences.setString('token', (token != null && token.length > 0) ? token : "");
await preferences.setInt('id', (id != null && id > 0) ? id : 0);
await preferences.setString('name', (name != null && name.length > 0) ? name : "");
await preferences.setString('email', (email != null && email.length > 0) ? email : "");
await preferences.setString('mobile', (mobile != null && mobile.length > 0) ? mobile : "");
await preferences.setInt('active', (active != null && active > 0) ? active : 0);
await preferences.setString('confirmation_code', (confirmation_code != null && confirmation_code.length > 0) ? confirmation_code : "");
await preferences.setInt('confirmed', (confirmed != null && confirmed > 0) ? confirmed : 0);
}
this is get token function code
import 'package:shared_preferences/shared_preferences.dart';
getToken() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
String getToken = await preferences.getString("token");
return getToken;
}
this is the new login model
class Login {
final String login;
final String password;
Login(this.login, this.password);
Login.fromJson(Map<String, dynamic> json)
: login = json['login'],
password = json['password'];
}
this is auth response model
import './User.dart';
class AuthResponse {
final String token;
User user;
AuthResponse({
this.token,
this.user,
});
factory AuthResponse.fromJson(Map<String, dynamic> parsedJson){
return AuthResponse(
token: parsedJson['token'],
user: User.fromJson(parsedJson['user'])
);
}
Map<String, dynamic> toJson() => {
'token': token,
'user':user,
};
}
this is my User model
class User {
final int id;
final String name;
final String email;
final String mobile;
final int active;
final String confirmation_code;
final int confirmed;
User({
this.id,
this.name,
this.email,
this.mobile,
this.active,
this.confirmation_code,
this.confirmed,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
mobile: json['mobile'],
active: json['active'],
confirmation_code: json['confirmation_code'],
confirmed: json['confirmed'],
);
}
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'email':email,
'mobile':mobile,
'active':active,
'confirmation_code':confirmation_code,
'confirmed':confirmed,
};
}
the best way to do this by using shared preferences
1 - you need to install dependence (see the link)
2 - make your "http" request with your server to get the "auth key"
3 - create tow "shared preferences" keys :
and give the first one the name of "auth_key" to store the authentication key
and save the other one as "bool" data type, give it the name "is_login"
now in the main function of the dart, check the parameter "is_login", if its true , countenu to (home page , account ... etc), otherwise take it to the login widget
dart code to set the two keys
Future<void> setUserLogin(String auth_token) async{
SharedPreferences pref = await SharedPreferences.getInstance();
pref.setString("auth_token", auth_token);
pref.setBool("is_login", true);
}
check if login:
Future<bool> isUserLogin() async{
SharedPreferences pref = await SharedPreferences.getInstance();
return pref.getBool("is_login");
}
get the auth key:
Future<bool> isUserLogin() async{
SharedPreferences pref = await SharedPreferences.getInstance();
return pref.getString("auth_token");
}
logout method
Future<void> logout() async{
SharedPreferences pref = await SharedPreferences.getInstance();
pref.remove("auth_key");
pref.remove("is_login");
}
I just give you an example of how to do it, you need to read more about "SharedPreferences" at the link below to know more about
there is another techniques like save data to sql, but its more complicated, and I guess its less secure (cuz there is many root apps working as sqlite browsers)