I want to make login system in flutter with the following code:
api/api.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class CallApi {
final String _url = 'http://10.0.2.2:8000/api/';
postData(data, apiUrl) async {
var fullUrl = _url + apiUrl + await _getToken();
return await http.post(fullUrl,
body: jsonEncode(data), headers: _setHeaders());
}
getData(apiUrl) async {
var fullUrl = _url + apiUrl + await _getToken();
return await http.get(fullUrl, headers: _setHeaders());
}
_setHeaders() => {
'Content-type': 'application/json',
'Accept': 'application/json',
};
_getToken() async {
SharedPreferences localStorage = await SharedPreferences.getInstance();
var token = localStorage.getString('token');
return '?token=$token';
}
}
login_screen.dart
void _login() async {
var data = {
'email': mailController.text,
'password': passwordController.text
};
var res = await CallApi().postData(data, 'login');
var body = json.decode(res.body);
if (body['success']) {
SharedPreferences localStorage = await SharedPreferences.getInstance();
localStorage.setString('token', body['token']);
localStorage.setString('user', json.encode(body['user']));
Navigator.push(
context, new MaterialPageRoute(builder: (context) => HomePage()));
} else {
_showMsg(body['message']);
}
}
The problem is this doesn't work. and after trying to find the location of the error, I found that the following code did not return anything
postData(data, apiUrl) async {
........
return await http.post(fullUrl,
body: jsonEncode(data), headers: _setHeaders());
}
I don't know the exact cause, please help me
Related
List is always empty even though body has contents. I am new to flutter so bare with me if this is basic. I am wanting to get back a list of station data I am coming from a c# background so forgive me if am missing something simple the test string body has the items and can see the items when i debug
class HttpService {
final String url = "url hidden";
final String host = 'url hidden';
final String apiSegment = "api/";
// ignore: non_constant_identifier_names
void login(email, password) async {
try {
Map<String, String> body = {
'username': email,
'password': password,
};
Map<String, String> headers = {'Content-Type': 'application/json'};
final msg = jsonEncode(body);
Response response =
await post(Uri.parse("$url/Login"), headers: headers, body: msg);
if (response.statusCode == 200) {
var data = jsonDecode(response.body.toString());
print(data['jwtToken']);
print('Login successfully');
final prefs = await SharedPreferences.getInstance();
await prefs.setString('jwtToken', data['jwtToken']);
List<Stations> stationData = await getStationData('11');
var test = stationData;
} else {
print('failed');
}
} catch (e) {
print(e.toString());
}
}
Future<List<Stations>> getStationData(String stationId) async {
final prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('jwtToken');
const String path = 'Station/GetAllStationData';
final uri = Uri.parse('$url/api/$path')
.replace(queryParameters: {'stationId': stationId});
List<Stations> stationData = <Stations>[];
try {
Response res = await get(uri, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
// 'Authorization': 'Bearer $token',
});
if (res.statusCode == 200) {
var body = jsonDecode(res.body);
var body2 = body.toString();
stationData = body
.map(
(dynamic item) => Stations.fromJson(item),
)
.toList();
} else {
throw "Unable to retrieve posts.";
}
} catch (e) {
print(e.toString());
}
return stationData;
}
}
I am calling my function from the same class
List<Stations> stationData = await getStationData('11');
Data from body
Actually the problem is you are returning the data after the end of try catch.
Try this
Future<List<Stations>> getStationData(String stationId) async {
final prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('jwtToken');
const String path = 'Station/GetAllStationData';
final uri = Uri.parse('$url/api/$path')
.replace(queryParameters: {'stationId': stationId});
try {
Response res = await get(uri, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
// 'Authorization': 'Bearer $token',
});
if (res.statusCode == 200) {
var body = jsonDecode(res.body);
final stationData = List<Stations>.from(body.map((item) => Stations.fromJson(item))); // made some changes
return stationData;
} else {
throw "Unable to retrieve posts.";
}
} catch (e) {
rethrow;
}
}
I hope this will help you
I need to use timeout if post request not working so, I write below code:
class APIService {
static var client = http.Client();
static Future<bool> login(LoginRequestModel model) async {
Map<String, String> requestHeaders = {
'Content-Type': 'application/json',
};
var url = Uri.http(Config.apiURL, Config.loginAPI);
try {
final response = await client
.post(
url,
headers: requestHeaders,
body: jsonEncode(model.toJson()),
)
.timeout(const Duration(seconds: 5));
print("response:");
print(response);
if (response.statusCode == 200) {
//SHARED
await SharedService.setLoginDetails(loginResponseJson(response.body));
return true;
} else {
return false;
}
} on TimeoutException catch (e) {
// handle timeout
return false;
}
}
But never end await client.post method waiting althouth I add timeout. How can I solve this ?
You can try this:
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart' as http;
final body = { 'email': email, 'password': password };
final client = http.Client();
http.Response res;
try {
res = await client
.post(
url,
headers: requestHeaders,
body: jsonEncode(model.toJson()),
.catchError((e) {
// SocketException would show up here, potentially after the timeout.
})
.timeout(const Duration(seconds: 5));
} on TimeoutException catch (e) {
// Display an alert, no internet
} catch (err) {
print(err);
return null;
}
how to retrieve token variable from sharedprefence in flutter?
i am very new to implement api for my flutter project because previously I was only told to work on the frontend, i have saved auth token in login and here is my code to store token in sharedprefence
signIn(String email, password) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
Map data = {
'email': email,
'password': password
};
var jsonResponse = null;
var response = await http.post(Uri.parse("/api/login"), body: data);
if(response.statusCode == 200) {
jsonResponse = json.decode(response.body);
if(jsonResponse != null) {
setState(() {
_isLoading = false;
});
sharedPreferences.setString("token", jsonResponse['data']['token']['original']['token']);
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => HomePage()), (Route<dynamic> route) => false);
}
}
else {
setState(() {
_isLoading = false;
});
scaffoldMessenger.showSnackBar(SnackBar(content:Text("Mohon cek Email dan Password kembali!", textAlign: TextAlign.center,), backgroundColor: Colors.red,));
}
}
and here is the darts place that I want to call the token for auth in the post method
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:kiriapp/models/angkot.dart';
class AngkotProvider with ChangeNotifier {
late AngkotModel _angkot;
AngkotModel get angkot => _angkot;
set angkot(AngkotModel newAngkot) {
_angkot = newAngkot;
notifyListeners();
}
static Future<AngkotModel?> tambah(
String user_id,
String route_id,
String plat_nomor,
String pajak_tahunan,
String pajak_stnk,
String kir_bulanan) async {
try {
var body = {
'user_id': user_id,
'route_id': route_id,
'plat_nomor': plat_nomor,
'pajak_tahunan': pajak_tahunan,
'pajak_stnk': pajak_stnk,
'kir_bulanan': kir_bulanan,
};
print(body);
var response = await http.post(
Uri.parse('api/create'),
headers: {
'Authorization': 'Bearer $howtocallthetoken?,
},
body: body,
);
print(response.statusCode);
print(response.body);
if (response.statusCode == 201) {
return AngkotModel.fromJson(jsonDecode(response.body));
} else if (response.statusCode == 400) {
return AngkotModel.fromJson(jsonDecode(response.body));
}{
return null;
}
} catch (e) {
print(e);
return null;
}
}
}
thanks
To store something in shared preference we use setString function, just like you did. Now to retrieve it, you should use getString and it will return the token you stored earlier.
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
String accessToken = sharedPreferences.getString("token");
var response = await http.post(
Uri.parse('api/create'),
headers: {
'Authorization': 'Bearer $accessToken',
},
body: body,
);
Don't forget to make the function async, and handle null values as the getString function might return token as null if not stored correctly.
I am trying to get from an API to get user data by accessToken. I don't know How to get data that authorize with AccessToken.
when the user is not logged in the app, they don't get any data from API (because API integrates with accessToken)
When I am logged in to the app, then I found a token
When logged into the app, then I found the data
How can I show the data from API?
This is my UserDataController:
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
class UserDataController extends GetxController {
final _dio = Dio();
final customerDataList = RxMap();
getuserData({String? id}) async {
try {
final sharedPreferences = await SharedPreferences.getInstance();
final value = sharedPreferences.setString('accessToken', '');
final res = await _dio.get(
'http://support.nbox.live:82/data/care_api/v1/$id',
options: Options(
headers: {
'Authorization': 'Bearer $value',
'Content-Type': 'application/json',
},
),
);
print('-----------------------');
print(value);
print('-----------------------');
if (res.statusCode == 200) {
print(res.data['data']['customer_info']);
customerDataList.value = res.data['data']['customer_info'];
}
} catch (e) {
print(e);
}
}
}
And, This is my LoginController:
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:isp_app/src/configs/appColors.dart';
import 'package:isp_app/src/pages/homePage.dart';
import 'package:isp_app/src/pages/loginPage.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginController extends GetxController {
final _dio = Dio();
//
final username = RxString('');
final password = RxString('');
//
getLoginUser() async {
try {
final sharedPreferences = await SharedPreferences.getInstance();
final value = sharedPreferences.get('accessToken');
final res = await _dio.post(
'http://support.nbox.live:82/login/',
data: {
'username': username.value,
'password': password.value,
},
options: Options(
headers: {
'Authorization': 'Bearer $value',
// 'Content-Type': 'application/json',
},
),
);
if (res.statusCode == 200) {
Get.snackbar(
'Success',
'Login Success',
);
currentUserToken(accessToken: res.data['token']);
await Get.offAll(HomePage());
}
} on Exception catch (e) {
print(e);
Get.snackbar(
'Error',
'User not found',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: white,
);
}
}
Future<String?> currentUserToken({
required String accessToken,
}) async {
final sharedPreferences = await SharedPreferences.getInstance();
await sharedPreferences.setString(
'accessToken',
accessToken,
);
if (accessToken.isNotEmpty) {
Get.offAll(HomePage());
}
print('Current user access token is $accessToken');
}
userSignOut({required String accessToken}) async {
final sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.remove(accessToken);
print('signout');
Get.to(LoginPage());
}
}
How to get the data and show the data into the app?
I am storing the token in SharedPreferences
For Postman Testing Api:
http://support.nbox.live:82/login/
username = admin
password = 123
how to pass the token value from above code to another screen into a http-request as variable.
class AppStarted extends AuthenticationEvent {}
class LoggedIn extends AuthenticationEvent {
final String token;
const LoggedIn({#required this.token});
#override
List<Object> get props => [token];
#override
String toString() => 'LoggedIn { token: $token }';
}
Thank you for your help, haning on this for 2 hours now...
first create a class where your where https request handle & token store
class Network {
var token;
final string base= "/api";
//token get when needed
_getToken() async {
SharedPreferences localStorage = await SharedPreferences.getInstance();
var user = jsonDecode(localStorage.getString('data'));
token = user['token'];
}
//signup
signUp(data, apiUrl) async {
var fullUrl = baseUrl + apiUrl;
return await http.post(fullUrl,
body: jsonEncode(data), headers: _setHeaders());
}
//login
signIn(apiUrl) async {
var fullUrl = baseUrl + apiUrl;
await _getToken();
return await http.get(fullUrl, headers: _setHeaders());
}
}
in sign up page use this method where you use sign up button on pressed
void _signUp() async {
var data = {
'mobile': mobileController.text,
'password': mobileController.text,
};
var res = await Network().signUp(data, '/register');
var body = json.decode(res.body);
if (body.statusCode == 200) {
SharedPreferences localStorage = await SharedPreferences.getInstance();
localStorage.setString('token', json.encode(body['data']['token']));
localStorage.setString('data', json.encode(body['data']));
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => Home()),
);
} else {
// errorMessage = "as you want to show ";
}
}
in sign up page , use this method same as sign up pages
void signIn() async {
var data = {'mobile': mobile, 'password': password};
var res = await Network().signIn(data, '/login');
var body = json.decode(res.body);
if (res.statusCode == 200) {
SharedPreferences localStorage = await SharedPreferences.getInstance();
localStorage.setString('token', json.encode(body['data']['token']));
localStorage.setString('data', json.encode(body['data']));
Navigator.pushReplacement(
context,
new MaterialPageRoute(builder: (context) => HomePage()),
);
} else if (res.statusCode != 200) {
// mobileError = "These credentials do not match our records.";
}
}
now you can have the token when u signup/singIn and store token in sharedSharedPreferences
whenever you try to acces token just called _getToken() method