I Want to get the token from my API by Dio flutter? - flutter

I'm trying to get my token from the API but it's empty
This is dio functions
import 'package:dio/dio.dart';
class DioHelper
{
static Dio dio;
static init()
{
print('dioHelper Initialized');
dio = Dio(
BaseOptions(
baseUrl:'my api link',
receiveDataWhenStatusError: true,
));
}
static Future<Response> getData ({
String url,
Map<String,dynamic> query,
String lang = 'en',
String token,
Map<String,dynamic> data,
})async
{
dio.options.headers =
{
'lang':'$lang',
'Content-Type':'application/json',
'Authorization' : '$token'
};
return await dio.get(
url,
queryParameters: query
);
}
static Future<Response> postData ({
String url,
Map<String,dynamic> query,
Map<String,dynamic> data,
String lang = 'ar',
String token
})async
{
dio.options.headers =
{
'lang':'$lang',
'Content-Type':'application/json',
'Authorization' : '$token'
};
return await dio.post(
url,
queryParameters: query,
data: data,
);
}
static Future<Response> putData ({
String url,
Map<String,dynamic> query,
Map<String,dynamic> data,
String lang = 'ar',
String token
})async
{
dio.options.headers =
{
'lang':'$lang',
'Content-Type':'application/json',
'Authorization' : '$token'
};
return await dio.put(
url,
queryParameters: query,
data: data,
);
}
static Future<Response> deleteData ({
String url,
String lang = 'ar',
String token
})async
{
dio.options.headers =
{
'lang':'$lang',
'Content-Type':'application/json',
'Authorization' : '$token'
};
return await dio.delete(url);
}
}
and pass value in this variable
String token = '';
and fuctions sharedPreferences
import 'package:shared_preferences/shared_preferences.dart';
class CacheHelper
{
static SharedPreferences sharedPreferences;
static init () async {
sharedPreferences = await SharedPreferences.getInstance();
}
static dynamic getData(String key, ){
return sharedPreferences.get(key);
}
static Future<bool> saveData({ String key, dynamic value})async{
if(value is String) return await sharedPreferences.setString(key, value);
if(value is int) return await sharedPreferences.setInt(key, value);
if(value is bool) return await sharedPreferences.setBool(key, value);
return await sharedPreferences.setDouble(key, value);
}
static Future<bool> removeData (String key)async{
return await sharedPreferences.remove(key);
}
}
*CALL THE TOKEN*
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
Bloc.observer = MyBlocObserver();
await DioHelper.init();
await CacheHelper.init();
token = CacheHelper.getData('token');
var IsLogin = CacheHelper.getData( 'IsLogin');
var IsBoarding = CacheHelper.getData( 'IsBoarding');
print(IsLogin);
print(IsBoarding);
print(token);
var widget;
if (IsBoarding != null) {
if (token == null) {
widget = ShopingScreen();
} else {
widget = Login_Screen();
}
} else {
widget = BordScreen();
}
THANKS
Is there any solution
I described my problem a few days ago, but without details, there was no useful solution
Tried a lot but it didn't solve this problem. I tried wiping the phone data or reformatting the codes and restarting the device several times.

Related

How to dynamically save token after logging to shared prefernces

How to dynamically auth users and save tokens in shared pref?
I understood how to save token in sharedprefernces, but can't understand how to take it dynamically by login/password and pass token from it to sharedpref dynamically in loginWithToken(); beacuse I use this function for auth in
final httpConnectionOptions = HttpConnectionOptions(
accessTokenFactory: () => SharedPreferenceService().loginWithToken(),
and it is required only String
My code now is like that:
Here is request where I am making request to get token:
Future<String?> getToken(String password, String login) async {
String _email = "admin";
String _password = "123";
Map<String, String> headers = {
'Content-Type': 'application/json',
'accept': ' */*'
};
final body = {
'username': _email,
'password': _password,
};
var response = await http.post(
Uri.parse("http://mylink/login"),
headers: headers,
body: jsonEncode(body),
);
if (response.statusCode == 200) {
var value = jsonEncode(response.body);
return value;
}
return null;
}
here is I created logging logic:
final TextEditingController _loginController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
ElevatedButton(
onPressed: () async {
var username = _loginController.text;
var password = _passwordController.text;
var jwt = await ProviderService()
.getToken(password, username);
if (jwt != null) {
SharedPreferenceService().setToken(jwt);
Navigator.pushNamed(
context, '/mainPageAdmin');
} else {
displayDialog(context);
}
},
here is my shared pref. I can't understand how to put new token value in that string, after paaword and login was sent.
String tokens = 'dhjwhdwdwkjdhdkje';
Future<bool> getSharedPreferencesInstance() async {
_prefs = await SharedPreferences.getInstance().catchError((e) {
print("shared preferences error : $e");
return false;
});
return true;
}
Future setToken(String token) async {
await _prefs?.setString('token', token);
}
Future clearToken() async {
await _prefs?.clear();
}
Future<String> get token async => _prefs?.getString('token') ?? '';
Future<String> loginWithToken() async {
bool value = await getSharedPreferencesInstance();
if (value == true) {
setToken("Bearer $tokens");
// print(tokens);
}
return tokens;
}
Api Responce:
{
"$id": "1",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZ",
"user": {
"$id": "2"
}
}
Auth class I parsed:
Auth authFromJson(String str) => Auth.fromJson(json.decode(str));
String authToJson(Auth data) => json.encode(data.toJson());
class Auth {
Auth({
this.token,
this.user,
});
final String? token;
final User? user;
factory Auth.fromJson(Map<String, dynamic> json) => Auth(
token: json["token"],
user: User.fromJson(json["user"]),
);
Map<String, dynamic> toJson() => {
"token": token,
"user": user!.toJson(),
};
}
In your getToken function do this:
if (response.statusCode == 200) {
var value = jsonEncode(response.body) as Map<String, dynamic>;
await setToken(value['token']);
return value;
}

An optimize way for tryAutoLogin function in flutter?

I want to create a function for auto login like Facebook in flutter but don't know the best way to do it.
My function for login and auto login, I used SharedPreferences plugin for store data.
SignIn function:
Future<void> signIn(String userName, String pass) async {
final url = Uri.parse('MyAPI_login');// sorry it for privacy
debugPrint("$userName / $pass");
try {
var respone = await http.post(url, body: {
'user_name': userName,
'password': pass,
'platform': 'mobile',
'device_token': '',
});
final reponseData = jsonDecode(respone.body);
_userName = userName;
_token = reponseData['data']['accessToken'];
_expiryDate = DateTime.now().add(Duration(
seconds: int.parse(reponseData['data']['tokenExpireAt'].toString())));
_refreshToken = reponseData['data']['refreshToken'].toString();
_timerRefreshToken =
int.parse(reponseData['data']['refreshTokenExpireAt'].toString());
// debugPrint(
// '$_token \n $_expiryDate \n $_refreshToken \n $_timerRefreshToken');
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode({
'_userId': _userName.toString(),
'token': _token.toString(),
'expiryDate': _expiryDate!.toIso8601String(),
'refreshToken': _refreshToken,
'timerRefreshToken': _timerRefreshToken.toString(),
});
await prefs.setString('userData', userData);
} catch (error) {
throw Exception(error.toString());
}}
TryAutoLogin function:
Future<bool> tryAutoLogin() async {
final prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey('userData')) {
return false;
}
final extractedUserData = json
.decode(prefs.getString('userData').toString()) as Map<String, dynamic>;
final expiryDate =
DateTime.parse(extractedUserData['expiryDate'].toString());
if (expiryDate.isBefore(DateTime.now())) {
_token = extractedUserData['refreshToken'].toString();
_expiryDate = DateTime.now().add(
Duration(seconds: int.parse(extractedUserData['timerRefreshToken'])));
_refreshNewToken(extractedUserData['refreshToken'].toString());
}
return true;}
RefreshNewToken function:
Future<void> _refreshNewToken(String oldRefreshToken) async {
final url =
Uri.parse('MyAPI_refreshtoken');
var respone = await http.post(url, body: {'refreshToken': oldRefreshToken});
debugPrint(respone.body);}
My API for login response is like this:
{"data":{"tokenKey":"Authorization","tokenType":"Bearer","accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl9pZCI6ImE1YzkyMTQwLTA3Y2YtMTFlZC1hNDQ2LTYzY2YyNjNiZjllMiIsInVzZXJfaWQiOiJDODAzQ0I3RS1CQTcyLTQ4NjgtQjdEMC05NkRBOUNCREQyMTkiLCJ1c2VyX25hbWUiOiIxMDAyMCIsImZ1bGxfbmFtZSI6IkzDqiBUaOG7iyBMacOqbiIsImlzQWRtaW5pc3RyYXRvciI6MCwidXNlcl9jb21wYW5pZXMiOltdLCJpYXQiOjE2NTgyODIzOTMsImV4cCI6MTY1ODI4NTk5M30.3kMByfweUhzQM-4d5S0G7tUaC0e-nZLJF3_dbdV_7fM","tokenExpireAt":1658285940964,"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl9pZCI6ImE1YzkyMTQwLTA3Y2YtMTFlZC1hNDQ2LTYzY2YyNjNiZjllMiIsInVzZXJfaWQiOiJDODAzQ0I3RS1CQTcyLTQ4NjgtQjdEMC05NkRBOUNCREQyMTkiLCJ1c2VyX25hbWUiOiIxMDAyMCIsImZ1bGxfbmFtZSI6IkzDqiBUaOG7iyBMacOqbiIsImlzQWRtaW5pc3RyYXRvciI6MCwidXNlcl9jb21wYW5pZXMiOltdLCJpYXQiOjE2NTgyODIzOTMsImV4cCI6MTY1ODM2ODc5M30.Bv7PZrnx9zDzwIuxNMppFxlwZlJEnthVjEYBKYl-aWM","refreshTokenExpireAt":1658368740964},"message":"Logged in successfully!","status":200,"errors":null}
Also, my API has a refresh token request, it returns like this:
{"data":{"tokenKey":"Authorization","tokenType":"Bearer","accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl9pZCI6ImE1ZjQyOGUwLTA3Y2YtMTFlZC1hNDQ2LTYzY2YyNjNiZjllMiIsInVzZXJfaWQiOiJDODAzQ0I3RS1CQTcyLTQ4NjgtQjdEMC05NkRBOUNCREQyMTkiLCJ1c2VyX25hbWUiOiIxMDAyMCIsImZ1bGxfbmFtZSI6IkzDqiBUaOG7iyBMacOqbiIsImlzQWRtaW5pc3RyYXRvciI6MCwidXNlcl9jb21wYW5pZXMiOltdLCJpYXQiOjE2NTgyODIzOTQsImV4cCI6MTY1ODI4NTk5NH0.wcyouoprMHFnRD4_oSpP9RSasxMBrktX6nZI2x2PQec","tokenExpireAt":1658285940242,"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl9pZCI6ImE1ZjQyOGUwLTA3Y2YtMTFlZC1hNDQ2LTYzY2YyNjNiZjllMiIsInVzZXJfaWQiOiJDODAzQ0I3RS1CQTcyLTQ4NjgtQjdEMC05NkRBOUNCREQyMTkiLCJ1c2VyX25hbWUiOiIxMDAyMCIsImZ1bGxfbmFtZSI6IkzDqiBUaOG7iyBMacOqbiIsImlzQWRtaW5pc3RyYXRvciI6MCwidXNlcl9jb21wYW5pZXMiOltdLCJpYXQiOjE2NTgyODIzOTQsImV4cCI6MTY1ODM2ODc5NH0.y-8MP4M_1LzCwmqo_KQZGyQXkycrxdOLWz_fdqIPRyQ","refreshTokenExpireAt":1658368740242},"message":"Request successfully!","status":200,"errors":null}

Get token auth value to another dart using sharedprefence

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.

how to set values in initState method using riverpod

right now i have a ChangeNotifierProvider, and i want to set some values straight in the initState method.
those values come from a backend API, that are retrieved in that provider.
I am stuck is this situation for a while now, hope i can get some help.
Here is the ChangeNotifierProvider
final userProvider = ChangeNotifierProvider.autoDispose.family<UserProxy, String>((ref, id) {
var notifier = UserProxy(userId: id);
notifier.load();
return notifier;
});
class UserProxy extends ChangeNotifier {
String userId;
User? user;
UserProxy({this.userId = ""});
void load() async {
await getUser().then((value) => generateObject(value));
}
Future<String> getUser() async {
Map<String, String> queryParams = {
"id": userId,
};
var url = Uri.https("asdadas.asdasd.com", "endpoint", queryParams);
Map<String, String> headers = {
'content-type': "application/json",
};
var response = await http.get(url,
headers: headers,);
print(response.body);
return response.body;
}
User generateObject(String jsonString) {
this.user = User.fromJson(jsonDecode(jsonString));
notifyListeners();
return this.user ?? User();
}
}
For this case I would suggest
FutureProvider.autoDispose.family<UserProxy, String>((ref, id) async { .... })
then change your StateWidget to ConsumerStatefulWidget and ConsumerState<>
then
ref.watch(provider(11)).when(
loading: (){},
error: (Object err, StackTrace? st){ },
data: (user){
// build widget with result here.
},
)

What the equivalent code in flutter dio compare to android retrofit #body?

Now I try to transform my Andorid project to flutter. but I stucked on an api call.
here is my android code in Kotlin:
/**
* sendSms
*
* #return
*/
#Headers("Content-Type: application/json;charset=UTF-8")
#POST("uaa/sms/send/code")
fun sendSms(#Body params: Map<String, String?>): Observable<ApiResult<String>>
Now I want to implement this api call in flutter use dio, but I still got wrong, my flutter code
is :
class Req {
static Req _instance;
static const int connectTimeOut = 5 * 1000;
static const int receiveTimeOut = 7 * 1000;
static Req getInstance() {
if (_instance == null) {
_instance = Req._internal();
}
return _instance;
}
Dio _client;
Req._internal() {
if (_client == null) {
BaseOptions options = new BaseOptions();
options.connectTimeout = connectTimeOut;
options.receiveTimeout = receiveTimeOut;
_client = new Dio(BaseOptions(
baseUrl: 'https://gw.ec.iunicorn.com/',
));
// 添加缓存插件
_client.interceptors.add(Global.netCache);
//添加token
_client.interceptors.add(Global.tokenInterceptor);
_client.interceptors.add(Global.logInterceptor);
// dio.options.headers[HttpHeaders.authorizationHeader] = Global.profile.token;
_client.options.headers['source'] = 'ANDROID';
if (!Global.isRelease) {
(_client.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
// client.findProxy = (uri) {
// return "PROXY 10.1.10.250:8888";
// };
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
};
}
}
}
//post请求
void post(
String url,
OnData callBack, {
Map<String, String> params,
Options options,
FormData formData,
OnError errorCallBack,
CancelToken token,
}) async {
this._request(
url,
callBack,
method: RequestType.POST,
options: options,
formData: formData,
params: params,
errorCallBack: errorCallBack,
token: token,
);
}
void _request(
String url,
OnData callBack, {
RequestType method,
Map<String, String> params,
Options options,
FormData formData,
OnError errorCallBack,
ProgressCallback progressCallBack,
CancelToken token,
}) async {
final id = _id++;
int statusCode;
try {
Response response;
if (method == RequestType.GET) {
if (mapNoEmpty(params)) {
response = await _client.get(url,
queryParameters: params, cancelToken: token);
} else {
response = await _client.get(url, cancelToken: token);
}
} else {
if (mapNoEmpty(params) || formData != null) {
response = await _client.post(
url,
data: formData ?? params,
onSendProgress: progressCallBack,
cancelToken: token,
);
} else {
response = await _client.post(url, cancelToken: token);
}
}
statusCode = response.statusCode;
if (response != null) {
if (response.data is List) {
Map data = response.data[0];
callBack(data);
} else {
Map data = response.data;
callBack(data);
}
print('HTTP_REQUEST_URL::[$id]::$url');
print('HTTP_REQUEST_BODY::[$id]::${params ?? ' no'}');
print('HTTP_RESPONSE_BODY::[$id]::${response.data}');
}
if (statusCode < 0) {
_handError(errorCallBack, statusCode);
return;
}
} catch (e) {
_handError(errorCallBack, statusCode);
}
}
///处理异常
static void _handError(OnError errorCallback, int statusCode) {
String errorMsg = 'Network request error';
if (errorCallback != null) {
errorCallback(errorMsg, statusCode);
}
print("HTTP_RESPONSE_ERROR::$errorMsg code:$statusCode");
}
}
void sendSms(BuildContext context, Callback callback) async {
Req.getInstance().post(
ApiPath.SEND_SMS,
(t) {
SmsResponse r = SmsResponse.fromJson(t);
print(r);
if (callback != null) {
callback();
}
},
formData: FormData.fromMap({
'phoneNumber':'182********'
}),
options: RequestOptions(
headers: {
HttpHeaders.contentTypeHeader: 'application/json;charset=UTF-8',
}),
errorCallBack: (msg, code) {
Fluttertoast.showToast(
msg: AppLocalizations.of(context).send_sms_fail,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
backgroundColor: Colors.orangeAccent,
timeInSecForIosWeb: 1);
});
}
Now I want to know is the data in dio is equivalent to the #Body in java retrofit, if not, how can I do?
Doing this in plain Dio leads to a lot of boilerplate. There is also an equivalent retrofit package for Flutter inspired by the same package for Android. https://pub.dev/packages?q=retrofit
From there it's almost the same, you just add () after #Body. Here is an example
#POST('/auth/change-password')
Future<bool> changePassword({
#required #Body() Map<String, dynamic> params,
#required #Header('auth-token') String token,
});