How to use shared preferences to save token in flutter? - flutter

I want to keep the user token in after the user successfully login in flutter.I am trying to save device token to SharedPreferences so I can use it in other widgets,but error is always : Invalid argument(s) (value): Must not be null . How i can save ID and access token ?
My code :
Future<User> login(String username, String password) async {
await checkInternet();
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
// 'Authorization': 'Bearer $token'
};
Map<String, String> body = {'username': username, 'password': password};
var response = await http.post(Uri.parse(ApiUtil.AUTH_LOGIN),
headers: headers, body: jsonEncode(body));
switch (response.statusCode) {
case 200:
var body = jsonDecode(response.body);
// print(body);
var data = body['user'];
// print(data);
User user = User.fromJson(data);
await _saveUser(user.id, user.access_token);
return user;
case 404:
throw ResourceNotFound('User');
break;
case 422:
throw UnProcessedEntity();
break;
case 401:
throw LoginFailed();
default:
return null;
break;
}
}
Future<void> _saveUser(int id, String access_token) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setInt('id', id);
sharedPreferences.setString('access_token', access_token);
}
}
and rhis the user model :
class User {
int id;
String name;
String email;
String username;
String phone;
String access_token;
String activeboxe_id;
String adress;
DateTime email_verifed_at;
User(this.name, this.email, this.username, this.phone, this.activeboxe_id,
this.adress, this.email_verifed_at,
[this.access_token, this.id]);
User.fromJson(Map<String, dynamic> jsonObject) {
this.id = jsonObject['id'];
this.name = jsonObject['name'];
this.email = jsonObject['email'];
this.phone = jsonObject['phone'];
this.access_token = jsonObject['access_token'];
this.activeboxe_id = jsonObject['activeboxe_id'];
this.adress = jsonObject['adress'];
this.email_verifed_at = jsonObject['email_verifed_at'];
this.username = jsonObject['username'];
}
}

First check if the values you are trying to save are not null and setInt or setString is an async function so you need to add await before them
Future<void> _saveUser(int id, String access_token) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
await sharedPreferences.setInt('id', id);
await sharedPreferences.setString('access_token', access_token);
}
And your User class is not return the .fromJson if you have noticed
class User {
int id;
String name;
String email;
String username;
String phone;
String access_token;
String activeboxe_id;
String adress;
DateTime email_verifed_at;
User(this.name, this.email, this.username, this.phone, this.activeboxe_id,
this.adress, this.email_verifed_at,
[this.access_token, this.id]);
// return a User object here
factory User.fromJson(Map<String, dynamic> jsonObject) => User({
this.id = jsonObject['id'];
this.name = jsonObject['name'];
this.email = jsonObject['email'];
this.phone = jsonObject['phone'];
this.access_token = jsonObject['access_token'];
this.activeboxe_id = jsonObject['activeboxe_id'];
this.adress = jsonObject['adress'];
this.email_verifed_at = jsonObject['email_verifed_at'];
this.username = jsonObject['username'];
});
}

Related

Flutter handle future response

i want to store token value and navigate home page using go router after login. i dont know how to handle json data like display or (retrieve)name and role.. i am newbie for programming.
Help me.thanks in advance.i tried futurebuilder examples it not worked. kindly give simple solution.
Future<Loginuser> fetchLoginuser(String mobile, String password) async {
final response = await http.post(
Uri.parse('https://random.url/api/login'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(
<String, String>{'mobile': mobile, 'password': password}));
if (response.statusCode == 200) {
return Loginuser.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to update album.');
}
}
class Userinfo {
double branchcode;
double role;
double name;
Userinfo({required this.branchcode, required this.role, required this.name});
factory Userinfo.fromJson(Map<String, dynamic> json) {
return Userinfo(
branchcode: json['branchcode'], role: json['role'], name: json['name']);
}
}
class Loginuser {
final String message;
final String messagecode;
final String token;
final Userinfo userinfo;
const Loginuser({
required this.message,
required this.messagecode,
required this.token,
required this.userinfo,
});
factory Loginuser.fromJson(Map<String, dynamic> json) {
return Loginuser(
message: json['message'],
messagecode: json['messagecode'],
token: json['token'],
userinfo: json['userinfo']);
}
}
Use shared_preferences usage is straight forward
here just do this
if (response.statusCode == 200) {
Loginuser _user = Loginuser.fromJson(json.decode(response.body));
final prefs = await SharedPreferences.getInstance();
await prefs.setString('token', user.token);
return user;
} else {
throw Exception('Failed to update album.');
}
And next time you want to check wether user was logged in or not
final prefs = await SharedPreferences.getInstance();
final String? action = prefs.getString('token');
if(token == null){ //not logged in}else{ //logged navigate to dashboard}
///Create a separate helper/manager for shared preferences. This is just an example///

Storing API Response in Flutter

I'm following an online trutorial to attempt to gain a better understanding of retreiving an API and storing it's response body to Hive.
In the online example i'm using i encounter an issue when attempting to store my response body. This is the error that i get;
Could any one give me any pointers to what i'm doing wrong?
My model
import 'package:hive_flutter/hive_flutter.dart';
part 'hive_solUser.g.dart';
#HiveType(typeId: 0) //, adapterName: "SolUserAdapter")
class GetSolUser {
#HiveField(0)
String? solUsername;
#HiveField(1)
bool? isUserActive;
#HiveField(2)
String? solSessionKey;
#HiveField(3)
String? firstame;
#HiveField(4)
String? lastName;
#HiveField(5)
int? id;
#HiveField(6)
String? email;
GetSolUser(
{required this.solUsername,
required this.isUserActive,
required this.solSessionKey,
required this.firstame,
required this.lastName,
required this.id,
required this.email});
GetSolUser.fromJson(Map<String, dynamic> json) {
solUsername = json['username'];
isUserActive = json['isUserActive'];
solSessionKey = json['solSessionKey'];
firstame = json['firstame'];
lastName = json['lastName'];
id = json['id'];
email = json['email'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['username'] = solUsername;
data['isUserActive'] = isUserActive;
data['solSessionKey'] = solSessionKey;
data['firstame'] = firstame;
data['lastName'] = lastName;
data['id'] = id;
data['email'] = email;
return data;
}
}
API Service
class APIServiceSolUser {
Future<bool> getSolUser(BuildContext context) async {
log("Requesting Sol User List...");
var solUserListResponse = await HTTPHandler()
.httpRequest(url: solUserURL, method: RequestType.GET);
final response = await http.get(Uri.parse(solUserURL));
//final solUserListResponse = jsonDecode(response.body);
if (response.statusCode != 200) {
return false;
} else {
log("Sol User API RESPONSE SUCCESSFUL");
var data = json.decode(response.body);
var data1 = solUserListResponse;
List<GetSolUser> solUserList =
List.from(data1.map((users) => GetSolUser.fromJson(users)));
await GetSolUserProvider().updateSolUserData(solUserList);
await GetSolUserProvider().saveOfflineData(solUserList);
return true;
}
}
}

Flutter Unhandled Exception: type 'Null' is not a subtype of type 'String'

I'm using GETX.
Now I've updated my all code. Anything you need tell me. Kindly I want to solve this problem today as I'm stuck here from 2 weeks and I can't figure out what is the reason behind.
Thanks
Registeration Code
void _freelancerRegistration(AuthController authController) {
SignUpBody signUpBody = SignUpBody(
name: name, email: email, password: password, phone: phone);
authController.registration(signUpBody).then((status) {
if (status.success!) {
print('sucess');
} else {
Utils.flushBarErrorMessage(status.enMessage!, context);
}
});
}
This is body which I want to pass from SignUp.
SignUpBody.dart
class SignUpBody {
SignUpBody({
String? name,
String? email,
String? password,
String? phone,
}) {
_name = name;
_email = email;
_password = password;
_phone = phone;
}
SignUpBody.fromJson(dynamic json) {
_name = json['name'];
_email = json['email'];
_password = json['password'];
_phone = json['phone'];
}
String? _name;
String? _email;
String? _password;
String? _phone;
SignUpBody copyWith({
String? name,
String? email,
String? password,
String? phone,
}) =>
SignUpBody(
name: name ?? _name,
email: email ?? _email,
password: password ?? _password,
phone: phone ?? _phone,
);
String? get name => _name;
String? get email => _email;
String? get password => _password;
String? get phone => _phone;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['name'] = _name;
map['email'] = _email;
map['password'] = _password;
map['phone'] = _phone;
return map;
}
}
This the response I'm getting from Postman and then I've created its model.
ResponseModel.dart
class ResponseModel {
ResponseModel({
bool? success,
String? enMessage,
String? arMessage,
Data? data,
int? status,
}) {
_success = success;
_enMessage = enMessage;
_arMessage = arMessage;
_data = data;
_status = status;
}
ResponseModel.fromJson(dynamic json) {
_success = json['success'];
_enMessage = json['en_message'];
_arMessage = json['ar_message'];
_data = json['data'] != null ? Data.fromJson(json['data']) : null;
_status = json['status'];
}
bool? _success;
String? _enMessage;
String? _arMessage;
Data? _data;
int? _status;
ResponseModel copyWith({
bool? success,
String? enMessage,
String? arMessage,
Data? data,
int? status,
}) =>
ResponseModel(
success: success ?? _success,
enMessage: enMessage ?? _enMessage,
arMessage: arMessage ?? _arMessage,
data: data ?? _data,
status: status ?? _status,
);
bool? get success => _success;
String? get enMessage => _enMessage;
String? get arMessage => _arMessage;
Data? get data => _data;
int? get status => _status;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['success'] = _success;
map['en_message'] = _enMessage;
map['ar_message'] = _arMessage;
if (_data != null) {
map['data'] = _data?.toJson();
}
map['status'] = _status;
return map;
}
}
/// user : {"first_name":"name","username":"","email":"xxff#gmail.com","type":1,"role_id":4,"verification_code":7257,"verified":0,"phone":"123456","updated_at":"2022-06-30T11:38:51.000000Z","created_at":"2022-06-30T11:38:51.000000Z","id":122,"balance":[{"AED":0}]}
class Data {
Data({
User? user,
}) {
_user = user;
}
Data.fromJson(dynamic json) {
_user = json['user'] != null ? User.fromJson(json['user']) : null;
}
User? _user;
Data copyWith({
User? user,
}) =>
Data(
user: user ?? _user,
);
User? get user => _user;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
if (_user != null) {
map['user'] = _user?.toJson();
}
return map;
}
}
class User {
User({
String? firstName,
String? username,
String? email,
int? type,
int? roleId,
int? verificationCode,
int? verified,
String? phone,
String? updatedAt,
String? createdAt,
int? id,
List<Balance>? balance,
}) {
_firstName = firstName;
_username = username;
_email = email;
_type = type;
_roleId = roleId;
_verificationCode = verificationCode;
_verified = verified;
_phone = phone;
_updatedAt = updatedAt;
_createdAt = createdAt;
_id = id;
_balance = balance;
}
User.fromJson(dynamic json) {
_firstName = json['first_name'];
_username = json['username'];
_email = json['email'];
_type = json['type'];
_roleId = json['role_id'];
_verificationCode = json['verification_code'];
_verified = json['verified'];
_phone = json['phone'];
_updatedAt = json['updated_at'];
_createdAt = json['created_at'];
_id = json['id'];
if (json['balance'] != null) {
_balance = [];
json['balance'].forEach((v) {
_balance?.add(Balance.fromJson(v));
});
}
}
String? _firstName;
String? _username;
String? _email;
int? _type;
int? _roleId;
int? _verificationCode;
int? _verified;
String? _phone;
String? _updatedAt;
String? _createdAt;
int? _id;
List<Balance>? _balance;
User copyWith({
String? firstName,
String? username,
String? email,
int? type,
int? roleId,
int? verificationCode,
int? verified,
String? phone,
String? updatedAt,
String? createdAt,
int? id,
List<Balance>? balance,
}) =>
User(
firstName: firstName ?? _firstName,
username: username ?? _username,
email: email ?? _email,
type: type ?? _type,
roleId: roleId ?? _roleId,
verificationCode: verificationCode ?? _verificationCode,
verified: verified ?? _verified,
phone: phone ?? _phone,
updatedAt: updatedAt ?? _updatedAt,
createdAt: createdAt ?? _createdAt,
id: id ?? _id,
balance: balance ?? _balance,
);
String? get firstName => _firstName;
String? get username => _username;
String? get email => _email;
int? get type => _type;
int? get roleId => _roleId;
int? get verificationCode => _verificationCode;
int? get verified => _verified;
String? get phone => _phone;
String? get updatedAt => _updatedAt;
String? get createdAt => _createdAt;
int? get id => _id;
List<Balance>? get balance => _balance;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['first_name'] = _firstName;
map['username'] = _username;
map['email'] = _email;
map['type'] = _type;
map['role_id'] = _roleId;
map['verification_code'] = _verificationCode;
map['verified'] = _verified;
map['phone'] = _phone;
map['updated_at'] = _updatedAt;
map['created_at'] = _createdAt;
map['id'] = _id;
if (_balance != null) {
map['balance'] = _balance?.map((v) => v.toJson()).toList();
}
return map;
}
}
/// AED : 0
class Balance {
Balance({
int? aed,
}) {
_aed = aed;
}
Balance.fromJson(dynamic json) {
_aed = json['AED'];
}
int? _aed;
Balance copyWith({
int? aed,
}) =>
Balance(
aed: aed ?? _aed,
);
int? get aed => _aed;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['AED'] = _aed;
return map;
}
}
AuthController.dart
class AuthController extends GetxController implements GetxService {
final AuthRepo authRepo;
AuthController({required this.authRepo});
bool _isLoading = false;
bool get isLoading => _isLoading;
Future<ResponseModel> registration(SignUpBody signUpBody) async {
_isLoading = true;
update();
Response response = await authRepo.registration(signUpBody);
late ResponseModel responseModel;
if (response.statusCode == 200) {
authRepo.saveUserToken(response.body["token"]);
responseModel =
ResponseModel(success: true, enMessage: response.body['token']);
} else {
responseModel =
ResponseModel(success: false, enMessage: response.statusText);
}
_isLoading = false;
update();
return responseModel;
}
Future<ResponseModel> login(String email, String password) async {
print('Getting Token');
print(authRepo.getUserToken().toString());
_isLoading = true;
update();
Response response = await authRepo.login(email, password);
late ResponseModel responseModel;
if (response.statusCode == 200) {
print('Backend Token');
authRepo.saveUserToken(response.body["token"]);
print(response.body['token'].toString());
responseModel =
ResponseModel(success: true, enMessage: response.body["token"]);
} else {
responseModel =
ResponseModel(success: false, enMessage: response.statusText!);
}
_isLoading = false;
update();
return responseModel;
}
}
AuthRepo.dart
class AuthRepo {
final ApiClient apiClient;
final SharedPreferences sharedPreferences;
AuthRepo({required this.apiClient, required this.sharedPreferences});
Future<Response> registration(SignUpBody signUpBody) async {
return await apiClient.postData(
AppConstants.REGISTRATION_URI, signUpBody.toJson());
}
Future<bool> saveUserToken(String token) async {
apiClient.token = token;
apiClient.updateHeader(token);
return await sharedPreferences.setString(AppConstants.TOKEN, token);
}
Future<Response> login(String email, String password) async {
return await apiClient.postData(
AppConstants.LOGIN_URI, {"email": email, "password": password});
}
Future<String> getUserToken()async{
return sharedPreferences.getString(AppConstants.TOKEN)??"";
}
}
ApiClient.dart
class ApiClient extends GetConnect implements GetxService {
late String token;
final String appBaseUrl;
late SharedPreferences sharedPreferences;
late Map<String, String> _mainHeaders;
ApiClient({required this.appBaseUrl, required this.sharedPreferences}) {
baseUrl = appBaseUrl;
timeout = const Duration(seconds: 30);
token = sharedPreferences.getString(AppConstants.TOKEN) ?? "";
_mainHeaders = {
'Accept': 'application/json',
'Authorization': 'Bearer $token',
};
}
void updateHeader(String token) {
_mainHeaders = {
'Accept': 'application/json',
'Authorization': 'Bearer $token',
};
}
Future<Response> postData(String uri, dynamic body) async {
print(body.toString());
try {
Response response = await post(uri, body, headers: _mainHeaders);
print(response.toString());
return response;
} catch (e) {
return Response(statusCode: 1, statusText: e.toString());
}
}
}
Without seeing your saveUserToken is difficult to say, but it seems that response.body["token"] is null and since saveUserToken will be something like saveUserToken(String token) { ... }, Dart is raising a type error.
I suggest you to check if your token is null or not and then throwing manually if it is. Something like this:
Future < ResponseModel > registration(SignUpBody signUpBody) async {
_isLoading = true;
update();
// no need of "late" here, you are function scoped
ResponseModel responseModel;
Response response;
try {
response = await authRepo.registration(signUpBody);
final String token = response.body["token"];
if (response.statusCode == 200 && token != null) {
await authRepo.saveUserToken();
responseModel = ResponseModel(success: true, enMessage: response.body['token']);
} else {
throw new Error('A custom message');
}
} on Error catch (e) {
print(e);
responseModel = ResponseModel(success: false, enMessage: response.statusText);
} finally {
_isLoading = false;
update();
}
return responseModel;
}
Check if response.body["token"] is really not null. You can output the variable via console. Otherwise send the whole error message. It is certainly not only one single line long.

Unhandled Exception: Converting object to an encodable object failed: Instance of 'LoginModel'

Am still learning and understanding the working of flutter, I am trying to save json string whenever a user logins in for the First time, and use the ID and token to call and interact with different API endpoints. Whenever I try to save the json content to Shared Preference I end with error
Unhandled Exception: Converting object to an encodable object failed:
Instance of 'LoginModel'
My LoginModel
import 'dart:convert';
LoginModel loginModelFromJson(String str) => LoginModel.fromJson(json.decode(str));
String loginModelToJson(LoginModel data) => json.encode(data.toJson());
class LoginModel {
LoginModel({
this.id,
this.username,
this.email,
this.roles,
this.userid,
this.surname,
this.firstname,
this.telephoneno,
this.whatsappno,
this.active,
this.studyrole,
this.tokenType,
this.accessToken,
});
int id;
String username;
String email;
List<String> roles;
String userid;
String surname;
String firstname;
String telephoneno;
String whatsappno;
int active;
String studyrole;
String tokenType;
String accessToken;
factory LoginModel.fromJson(Map<String, dynamic> json) => LoginModel(
id: json["id"],
username: json["username"],
email: json["email"],
roles: List<String>.from(json["roles"].map((x) => x)),
userid: json["userid"],
surname: json["surname"],
firstname: json["firstname"],
telephoneno: json["telephoneno"],
whatsappno: json["whatsappno"],
active: json["active"],
studyrole: json["studyrole"],
tokenType: json["tokenType"],
accessToken: json["accessToken"],
);
Map<String, dynamic> toJson() => {
"id": id,
"username": username,
"email": email,
"roles": List<dynamic>.from(roles.map((x) => x)),
"userid": userid,
"surname": surname,
"firstname": firstname,
"telephoneno": telephoneno,
"whatsappno": whatsappno,
"active": active,
"studyrole": studyrole,
"tokenType": tokenType,
"accessToken": accessToken,
};
}
how am trying to save the Json to shared pref when user clicks on the login button
login(username, password) async {
SharedPref sharedPref = SharedPref();
LoginModel userSave = LoginModel();
final String url = "http://21.76.45.12:80/data/api/auth/signin"; // iOS
final http.Response response = await http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'username': username,
'password': password,
}),
);
print(response.body);
sharedPref.save("user", userSave);
}
My Login button Widget
RoundedButton(
text: "LOGIN",
press: () async {
if (_formKey.currentState.validate()) {
progressDialog.show();
await login(
username,
password,
);
SharedPreferences prefs =
await SharedPreferences.getInstance();
String token = prefs.getString("accessToken");
loadSharedPrefs();
print(token);
// ignore: null_aware_in_condition
if (token == null) {
progressDialog.hide();
showAlertsDialog(context);
// ignore: null_aware_in_condition
} else {
progressDialog.hide();
showAlertzDialog(context);
}
}
},
),
whenever I try to load the preference I get no data
loadSharedPrefs() async {
try {
LoginModel user = LoginModel.fromJson(await sharedPref.read("user"));
Scaffold.of(context).showSnackBar(SnackBar(
content: new Text("Loaded!"),
duration: const Duration(milliseconds: 500)));
setState(() {
userLoad = user;
});
} catch (Excepetion) {
Scaffold.of(context).showSnackBar(SnackBar(
content: new Text("Nothing found!"),
duration: const Duration(milliseconds: 500)));
}
}
My SharedPref class
class SharedPref {
read(String key) async {
final prefs = await SharedPreferences.getInstance();
return json.decode(prefs.getString(key));
}
save(String key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, json.encode(value));
}
remove(String key) async {
final prefs = await SharedPreferences.getInstance();
prefs.remove(key);
}
}
what am I doing wrong such that the JSON is not being saved to shared prefs? Thank you for the help
You are not parsing the json anywhere in your code. You are creating an empty object using:
LoginModel userSave = LoginModel();
Which contains null values for the properties and that's why you are getting those exceptions. You want to parse the json and create the object using:
LoginModel userSave = loginModelFromJson(response.body);
sharedPref.save("user", userSave);

About Firebase real time database

I am working on Firebase real time databases in Flutter. I am storing user information and their corresponding data in database. My code is given below:
//User Auth Class
class UserAuth{
final String id;
final String email;
final String token;
UserAuth({#required this.id, #required this.email, #required this.token});
}
//User Details Class for storing data of corresponding user
class UserDetails{
final String userDetailsId;
final String name;
final String email;
UserDetails({#required this.userDetailsId,#required this.name, #required this.email});
}
//I am using this code to add userDetails in database.
List<UserDetails> _detailsList = [];
UserDetails _details;
Future<bool> addUserDetails(String username, String email) async {
_isLoading = true;
notifyListeners();
final Map<String, dynamic> userDetails = {
'username': username,
'email': email,
};
try {
final http.Response response = await http.post(
'https://intro-to-firebase-711d4.firebaseio.com/Users.json',
body: json.encode(userDetails));
if (response.statusCode != 200 && response.statusCode != 201) {
_isLoading = false;
notifyListeners();
return false;
}
final Map<String, dynamic> responseData = json.decode(response.body);
_details = UserDetails(
userDetailsId: responseData['name'], name: username, email: email);
_detailsList.add(_details);
_isLoading = false;
notifyListeners();
return true;
} catch (error) {
_isLoading = false;
notifyListeners();
return false;
}
}
Now I want to get the following highlighted ids of the user so how to fetch it. I am using scoped model as a state management in Flutter.
I did it with javascript so far but in the documentation it seems not taht different for flutter:
private void writeNewUser(String userId, String name, String email) {
User user = new User(name, email);
mDatabase.child("users").child(userId).setValue(user);
}
https://firebase.google.com/docs/database/android/read-and-write?authuser=0
This is the example shown in the docs. with .child('users') you can get the right section .child(userId) gives you access to the values.
All you have to do now is defining the variable userId
flutter
you can achieve this as follows
stream: FirebaseDatabase.instance
.reference()
.child('users')
.equalTo(userId)
.onValue,