How to access dio onResponse.statuscode in catch code - flutter

I am trying to create a login form, where i am trying to display a pop-up dialogue when server is not running, on invalid credentials and on when internet is not connected. here is my code.
var data={};
Future login() async {
Dio dio = new Dio();
try {
data = {
'username':user.username,
'password':user.password,
'date': formattedDate
};
await dio
.post(localhostUrlLogin, data: json.encode(data),)
.then((onResponse) async {
Navigator.push(
context, new MaterialPageRoute(builder: (context) => Navigation()));
});
} catch (e) {
print(OSError.noErrorCode);
if (OSError.noErrorCode== -1) {
showDialog(
context: context,
builder: (BuildContext context) {
return AdvanceCustomAlert(
title: "Connection Error",
descriptions: "Connection error",
icon: Icons.error,
bgcolor: Colors.red,
fgcolor: Colors.red,
);
});
} else {
print("con er");
showDialog(
context: context,
builder: (BuildContext context) {
return AdvanceCustomAlert(
title: "Try Again",
descriptions: "Invalid username or password!",
icon: Icons.error,
bgcolor: Colors.red,
fgcolor: Colors.red,
);
});
}
}
}
i am getting OSError.noErrorCode -1 all on all condition, i am passing invalid input error on backend (api) but i can't access the onResponse after the try code.
kindly let me know how i can do this.

You can handle dio errors in a proper way as follows
try {
Response response = await allDataRepository.getData();
print(response.toString());
} on DioError catch (dioError) {
print(dioError);
if (dioError.type == DioErrorType.response) {
switch (dioError.response!.statusCode) {
case 404:
log(error: '400 - Not found');
break;
case 401:
log(error: '401 - Unauthorized.');
break;
case 500:
log(error: '500 - Internal Server Error.');
break;
case 501:
log(error: '501 - Not Implemented Server Error.');
break;
case 502:
log(error: '502 - Bad Gateway Server Error.');
break;
default:
log(error: '${dioError.response!.statusCode} - Something went wrong while trying to connect with the server');
break;
}
} else if (dioError.type == DioErrorType.other) {
log(error: 'Please check your internet connection. Try again switching to a different connection');
}
} catch (e) {
log(error: 'Something went wrong : $e');
}
Repository should look like this (data_repository.dart)
class DataRepository {
final HttpClient httpClient;
DataRepository({required this.httpClient});
Future<Response> getData() async {
Response response = await httpClient.dio.get(
GlobalConfig.getDataUrl,
);
return response;
}
}
HttpClient should look like this (http_client.dart)
class HttpClient {
final Dio dio;
HttpClient({required this.dio});
static final String basePath = GlobalConfig.baseUrl;
void addBasePathInterceptor() {
dio.interceptors.add(InterceptorsWrapper(
onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
print(options.uri);
if (!options.path.startsWith("http")) {
options.baseUrl = basePath;
}
return handler.next(options);
},
));
addUrlInterceptor();
// addVersionInterceptor();
}
Interceptor? sessionCookieInterceptor;
Interceptor? versionCookieInterceptor;
Interceptor? status401Interceptor;
// void addSessionCookieInterceptor(List<String> cookies) {
// sessionCookieInterceptor = InterceptorsWrapper(
// onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
// options.headers['cookie'] = cookies.join(';');
// });
// dio.interceptors.add(sessionCookieInterceptor!);
// }
// void addVersionInterceptor() {
// versionCookieInterceptor = InterceptorsWrapper(
// onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
// options.headers['website-version'] = '26.3.0';
// });
// dio.interceptors.add(versionCookieInterceptor!);
// }
void addUrlInterceptor() {
dio.interceptors.add(InterceptorsWrapper(
onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
print('onRequest ${options.uri}');
return handler.next(options);
},
onResponse: (Response response, ResponseInterceptorHandler handler) {
print('onResponse ${response.statusCode} ${response.realUri}');
return handler.next(response);
},
onError: (DioError error, ErrorInterceptorHandler handler) {
if (error.type == DioErrorType.response) {
print('------------------------');
print(error.error);
print(error.response?.realUri);
print(error.response?.statusCode);
print(error.response?.data);
print('------------------------');
}
return handler.next(error);
},
));
}
void add401Interceptor() {
print("Adding 401 interceptor");
status401Interceptor = InterceptorsWrapper(
onError: (DioError res, ErrorInterceptorHandler handler) {
if (res.response != null && res.response?.statusCode == 401) {
// globalBloc.add(ShowErrorSnackBar(
// error: 'You have been logged out, Please login again'));
// authenticationBloc.add(AuthenticationUnauthenticatedEvent());
// mainBloc.add(LougoutEvent());
}
return handler.next(res);
});
dio.interceptors.add(status401Interceptor!);
}
// void remove401Interceptor() {
// dio.interceptors.remove(status401Interceptor);
// }
}
Finally, Initialize HttpClient as below in main.dart
void main() async {
// Intializing Http Client
HttpClient(dio: sl()).addBasePathInterceptor();
runApp(MyApp());
}
Please note that you only need the following bunch of code. But I have described a good way to handle every API call in your app.
Dio dio = new Dio();
try {
Response response = await dio.get(GlobalConfig.getDataUrl);
print(response.toString());
} on DioError catch (dioError) {
print(dioError);
if (dioError.type == DioErrorType.response) {
switch (dioError.response!.statusCode) {
case 404:
log(error: '400 - Not found');
break;
case 401:
log(error: '401 - Unauthorized.');
break;
case 500:
log(error: '500 - Internal Server Error.');
break;
case 501:
log(error: '501 - Not Implemented Server Error.');
break;
case 502:
log(error: '502 - Bad Gateway Server Error.');
break;
default:
log(error: '${dioError.response!.statusCode} - Something went wrong while trying to connect with the server');
break;
}
} else if (dioError.type == DioErrorType.other) {
log(error: 'Please check your internet connection. Try again switching to a different connection');
}
} catch (e) {
log(error: 'Something went wrong : $e');
}

Related

Flutter Web - set-cookie is not in the response headers

I have called an API for login and the cookies from server is there in network section in dev-tools in google chrome. I am attaching the screenshots and the code for reference.
We are using dio package for the network.
Code
static Future<void> request({
required HttpMethod? method,
bool hideLoadingIndicator = false,
required String? path,
required Map? params,
required BuildContext context,
required OnResponse onResponse,
}) async {
try {
if (!hideLoadingIndicator) {
showLoading(context);
}
Response response;
switch (method) {
case HttpMethod.post:
response = await DioFactory.dio!.post(
path!,
options: Options(headers: {
HttpHeaders.contentTypeHeader: "application/json",
}),
data: params,
);
break;
case HttpMethod.delete:
response = await DioFactory.dio!.delete(
path!,
data: params,
);
break;
case HttpMethod.get:
response = await DioFactory.dio!.get(
path!,
);
break;
case HttpMethod.patch:
response = await DioFactory.dio!.patch(
path!,
data: params,
);
break;
case HttpMethod.put:
response = await DioFactory.dio!.put(
path!,
options: Options(headers: {
HttpHeaders.contentTypeHeader: "application/json",
}),
data: params,
);
break;
default:
return;
}
print("----whole response----->>>>>>>>> $response");
print("------rawCookies--->>>>>>>>> ${response.headers.map}");
if (!hideLoadingIndicator) {
hideLoading(context);
}
if (response.statusCode == 401) {
showSessionDialog(context);
} else if (response.data["success"] == 0) {
List errors = response.data['error'];
if (errors.isNotEmpty) {
// handleApiError(errors.first ?? "");
handleApiError(errors.first ?? "", context);
} else {
handleApiError("Something went wrong! Please try again.", context);
}
// handleApiError(response.data["error"]["message"]);
// onError!(response.data["error"][0], {});
} else {
onResponse(response.data);
// onResponse!(BaseResponse.fromJson(response.data));
}
} catch (e) {
if (!hideLoadingIndicator) {
hideLoading(context);
}
String errorMessage = "";
if (e is DioError) {
if (e.type == DioErrorType.connectTimeout ||
e.type == DioErrorType.sendTimeout ||
e.type == DioErrorType.receiveTimeout ||
e.type == DioErrorType.other) {
errorMessage = 'Server unreachable';
} else if (e.type == DioErrorType.response) {
if (e.response!.statusCode == 401) {
PrefUtils.clearPrefs();
} else {
final response = e.response;
List errors = response?.data['error'];
if (errors.isNotEmpty) {
errorMessage = errors.first;
} else {
errorMessage = "Something went wrong! Please try again.";
}
}
} else {
errorMessage = "Request cancelled";
}
} else {
errorMessage = e.toString();
}
handleApiError(errorMessage, context);
}
}
I am getting this errors and in the Applications tab the cookie is not stored and also not there in the response headers log you can see in the image.

Catching and handling exception in flutter future http request method called from different class

I have class with static Future method that makes http request. This method is encapsulated within try catch. Most of the exception is handled here.
class AuthenticationServices {
static late User users;
static Future<int> loginWithUernameAPI(
String username, String password) async {
try {
Map loginData = {'username': username, 'password': password};
final responseLoginUser = await http.post(
Uri.parse(Constants.userLogin),
headers: {
'Accept': 'application/json'
},
body: loginData,
);
if (responseLoginUser.statusCode == 200) {
return responseLoginUser.statusCode;
} else {
return responseLoginUser.statusCode;
}
} on SocketException catch (e) {
developer.log(e.toString(), name: 'SocketException');
} on TimeoutException catch (e) {
developer.log(e.toString(), name: 'TimeoutException');
} on HttpException catch (e) {
developer.log(e.toString(), name: 'HttpException');
} on Exception catch (e) {
developer.log(e.toString(), name: 'Exception');
} catch (e) {
developer.log(e.toString(), name: 'Exception');
}
}
}
This method is called from another route. Like below
AuthenticationServices.loginWithUernameAPI(
_usernameController.text,
_passwordController.text)
.then((value) {
responseStatusCode = value;
if (responseStatusCode == 200) {
developer.log("autheticated");
context.loaderOverlay.hide();
Navigator.pushAndRemoveUntil<MenuActivity>(
context, MaterialPageRoute(
builder: (BuildContext context) {
return const MenuActivity();
},
), (Route<dynamic> route) => false);
} else if (responseStatusCode == 404) {
context.loaderOverlay.hide();
developer.log("not autheticated");
} else {
developer.log(responseStatusCode.toString());
context.loaderOverlay.hide();
developer.log("not autheticated");
}
}).timeout(const Duration(seconds: 10),
onTimeout: () {
context.loaderOverlay.hide();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(Constants.connectionTimedOut),
duration: Duration(seconds: 3),
),
);
});
When I produce error, app crashes, throws an exception which is not the behavior I want.I am trying here to provide suitable error according to the exception generated.
Note: I have added breakpoint to debug. The app is routed to try catch only after throwing exception which is not handled by the defined try catch.
I suppose you want to show snackbar on errors. So you can rethrow the exceptions and catch them in your method call itself. The other option is to create a model class ExceptionModel where you can pass the message and then return it from the method and then show snackbar.

Appodeal Consent Manager won't show

Future<void> checkConsent() async {
ConsentManager.requestConsentInfoUpdate(Constants.kAppodealKey);
ConsentManager.setConsentInfoUpdateListener(
(onConsentInfoUpdated, consent) {
print('PRINT: onConsentInfoUpdated $consent');
}, (onFailedToUpdateConsentInfo, error) {
print('PRINT: onFailedToUpdateConsentInfo $error');
});
var consentStatus = await ConsentManager.getConsentStatus();
print('PRINT: consentStatus $consentStatus');
if (consentStatus.toString() == 'Status.UNKNOWN') {
var shouldShow = await ConsentManager.shouldShowConsentDialog();
print('PRINT: shouldShow $shouldShow');
if (shouldShow.toString() == 'ShouldShow.TRUE') {
ConsentManager.loadConsentForm();
var isLoaded = await ConsentManager.consentFormIsLoaded();
print('PRINT: isLoaded $isLoaded');
if (isLoaded == true) {
ConsentManager.showAsDialogConsentForm();
ConsentManager.showAsActivityConsentForm();
ConsentManager.setConsentFormListener((onConsentFormLoaded) {
print('PRINT: onConsentFormLoaded');
}, (onConsentFormError, error) {
print('PRINT: onConsentFormError $error');
}, (onConsentFormOpened) {
print('PRINT: onConsentFormOpened');
}, (onConsentFormClosed, consent) {
print('PRINT: onConsentFormClosed $consent');
});
}
}
}
}
Constants.kAppodealKey is what I got in the Application key from here: https://app.appodeal.com/apps
But this is what I got:
I/flutter ( 9497): PRINT: consentStatus Status.UNKNOWN
I/flutter ( 9497): PRINT: shouldShow ShouldShow.UNKNOWN
In the documentation ShouldShow.UKNOWN means this: https://wiki.appodeal.com/en/android/get-started/data-protection/gdpr-and-ccpa
UNKNOWN The value is undefined(the requestConsentInfoUpdate method was not called).
But I have called it on the first line of my method. May I know why it is having a problem?
Important update 2022 07 18
less than 10 days after I posted this answer, a new Flutter Appodeal plugin (3.0.0) was made available which is claimed to make the handling of consent much easier.
Old answer
I was able to reproduce your issue with your code, my verified app key and those prints on the first attempt after app installation:
I/flutter (21755): PRINT: consentStatus Status.UNKNOWN
I/flutter (21755): PRINT: shouldShow ShouldShow.UNKNOWN
I/flutter (21755): PRINT: onConsentInfoUpdated {"createdAt":1655890242,"zone":"NONE","acceptedVendors":[],"iab":{"IABConsent_SubjectToGDPR":"0"},"updatedAt":1655890242,"status":"UNKNOWN"}
The main problem here is that you cannot rely on the end of the execution of a method call to consider its work completed. Even with await.
You have to either rely on retry and wait loops which I don't recommend as it can be intensive and it can fail easily.
Or you can rely on the listeners.
What I did, is a mix of both because listeners are not always available.
I would love to get some feedback on this proposal as I am not certain I interpreted correctly the AppoDeal documentation.
I call AdManager.init(); once the app is loaded. This may also work if called earlier.
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:stack_appodeal_flutter/stack_appodeal_flutter.dart';
import 'dart:io' show Platform;
class AdManager {
static var consent = false;
static Status consentStatus = Status.UNKNOWN;
static int requestConsentInfoUpdateRetries = 20;
static int requestLoadConsentFormRetries = 20;
static int adType = Appodeal.INTERSTITIAL;
static String get appKey =>
Platform.isAndroid ?
"your android app key"
:
"your ios app key"
;
//app ids found here: https://app.appodeal.com/apps
static initializeAfterConsent() {
Appodeal.initialize(
appKey,
[
adType,
],
boolConsent: consent,
).whenComplete(() {
Appodeal.isLoaded(adType).then((bool isLoaded) {
if (!isLoaded) {
Appodeal.cache(adType).whenComplete(() {
debugPrint("Note: appodeal ad has been loaded");
});
}
else {
debugPrint("Note: appodeal ad was loaded");
}
});
});
}
static init(bool testing) async {
try {
await handleATT();
await Appodeal.setTesting(true);
await Appodeal.setLogLevel(Appodeal.LogLevelVerbose);
await Appodeal.disableNetwork("admob");
await Appodeal.setAutoCache(adType, true);
await Appodeal.setAutoCache(Appodeal.REWARDED_VIDEO, false);
await Appodeal.setAutoCache(Appodeal.BANNER, false);
await Appodeal.setAutoCache(Appodeal.MREC, false);
await Appodeal.setChildDirectedTreatment(false);
await Appodeal.setUseSafeArea(true);
await Appodeal.muteVideosIfCallsMuted(true);
await doTheConsentStuff();
}
catch (e, st) {
debugPrint("Error initializing ads: ${e.toString()} ${st.toString()}");
}
}
static Future<String> showInterstitialAd(
{Function doWhenComplete, int retries = 10}) async {
try {
Map<String, Function> callsForAd = {
"not initialized": () async {
return await Appodeal.isInitialized(adType);
},
"not loaded": () async {
return await Appodeal.isLoaded(adType);
},
"cannot show": () async {
return await Appodeal.canShow(adType);
},
"not shown": () async {
return await Appodeal.show(adType);
},
};
for (int i = 0; i < callsForAd.length; i++) {
if (!await callsForAd.values.toList()[i]()) {
String res = callsForAd.keys.toList()[i];
switch (res) {
case "not initialized":
await initializeAfterConsent();
break;
case "not loaded":
await Appodeal.cache(adType);
break;
case "cannot show":
case "not shown":
if (retries > 0) {
await Future.delayed(Duration(milliseconds: 100));
}
break;
default:
return (res);
break;
}
if (retries > 0) {
debugPrint(
"Warning from ads: " + res + "; with retries: $retries");
return (await showInterstitialAd(
doWhenComplete: doWhenComplete, retries: retries - 1));
}
return (res);
}
else {
if (doWhenComplete != null) {
doWhenComplete();
}
}
}
return (null);
}
catch (e, st) {
return ("${e.toString()} ${st.toString()}");
}
}
static retryMaybeConsentInfoUpdate() {
if (requestConsentInfoUpdateRetries > 0) {
Future.delayed(Duration(milliseconds: 2000)).whenComplete(() {
requestConsentInfoUpdateRetries--;
ConsentManager.requestConsentInfoUpdate(appKey);
});
}
else {
debugPrint(
"Error: exhausted all retries on retryMaybeConsentInfoUpdate, aborting consent handling");
initializeAfterConsent();
}
}
static retryMaybeLoadConsentForm() {
if (requestLoadConsentFormRetries > 0) {
Future.delayed(Duration(milliseconds: 2000)).whenComplete(() {
requestLoadConsentFormRetries--;
ConsentManager.loadConsentForm();
});
}
else {
debugPrint(
"Error: exhausted all retries on requestLoadConsentFormRetries, aborting consent handling");
initializeAfterConsent();
}
}
static doTheConsentStuff() async {
try {
ConsentManager.setConsentInfoUpdateListener(
(onConsentInfoUpdated, consent) {
debugPrint(
"Note: Appodeal consent onConsentInfoUpdated: $onConsentInfoUpdated : $consent");
if (onConsentInfoUpdated == "onConsentInfoUpdated") {
try {
Map<String, dynamic> result = jsonDecode(consent);
switch (result["status"]) {
case "UNKNOWN":
debugPrint("Note: got a consent info status of unknown");
updateConsentStatus().whenComplete(() {
getShouldShow().then((shouldShow) {
switch (shouldShow) {
case ShouldShow.TRUE:
ConsentManager.setConsentFormListener(
(onConsentFormLoaded) {
debugPrint(
"Note: consent form loaded: $onConsentFormLoaded");
if (Platform.isIOS) {
ConsentManager.showAsActivityConsentForm();
}
else {
ConsentManager.showAsDialogConsentForm();
}
},
(onConsentFormError, error) {
debugPrint(
"Error: consent form error: $onConsentFormError: $error");
if (error == "Nothing to load") {
updateConsentStatus().whenComplete(() {
initializeAfterConsent();
});
}
else {
retryMaybeLoadConsentForm();
}
},
(onConsentFormOpened) {
debugPrint(
"Note: consent form opened: $onConsentFormOpened");
},
(onConsentFormClosed, consent) {
debugPrint(
"Note: consent form closed: $onConsentFormClosed: $consent");
updateConsentStatus().whenComplete(() {
initializeAfterConsent();
});
}
);
ConsentManager.loadConsentForm();
break;
case ShouldShow.FALSE:
debugPrint("Note: no need to show consent form");
updateConsentStatus().whenComplete(() {
initializeAfterConsent();
});
break;
case ShouldShow.UNKNOWN:
retryMaybeConsentInfoUpdate();
break;
default:
debugPrint(
"Error: undefined consent shouldShow value, aborting consent handling");
initializeAfterConsent();
break;
}
});
});
break;
case "PARTLY_PERSONALIZED":
debugPrint(
"Note: got a consent info status of PARTLY_PERSONALIZED");
updateConsentStatus().whenComplete(() {
initializeAfterConsent();
});
break;
case "PERSONALIZED":
debugPrint(
"Note: got a consent info status of PERSONALIZED");
updateConsentStatus().whenComplete(() {
initializeAfterConsent();
});
break;
case "NON_PERSONALIZED":
debugPrint(
"Note: got a consent info status of NON_PERSONALIZED");
updateConsentStatus().whenComplete(() {
initializeAfterConsent();
});
break;
default:
debugPrint("Error: got an unknown consent info status");
retryMaybeConsentInfoUpdate();
break;
}
}
catch (e, st) {
debugPrint("Error reading onConsentInfoUpdated data");
retryMaybeConsentInfoUpdate();
}
}
},
(onFailedToUpdateConsentInfo, error) {
debugPrint(
"Note: Appodeal consent onFailedToUpdateConsentInfo: $onFailedToUpdateConsentInfo : $error with $requestConsentInfoUpdateRetries retries");
retryMaybeConsentInfoUpdate();
});
await ConsentManager.requestConsentInfoUpdate(appKey);
}
catch (e, st) {
debugPrint("Error: consent form general error: ${e.toString()} ${st
.toString()}");
}
}
static Future<void> updateConsentStatus() async {
consentStatus = await ConsentManager.getConsentStatus();
switch (consentStatus) {
case Status.UNKNOWN:
debugPrint("Warning: consent status is unknown");
consent = false;
break;
case Status.NON_PERSONALIZED:
case Status.PARTLY_PERSONALIZED:
consent = false;
break;
case Status.PERSONALIZED:
debugPrint("Note: consent status is known");
consent = true;
break;
default:
consent = false;
debugPrint("Warning: undefined consent status");
break;
}
}
static Future<ShouldShow> getShouldShow([int retries = 20]) async {
var shouldShow = await ConsentManager.shouldShowConsentDialog();
if (shouldShow == ShouldShow.UNKNOWN) {
if (retries > 0) {
await Future.delayed(Duration(milliseconds: 500));
return (getShouldShow(retries - 1));
}
}
return (shouldShow);
}
static Future<void> handleATT({int retries = 20}) async {
if (Platform.isIOS) {
Permission appTrackingTransparencyPermission = Permission
.appTrackingTransparency;
PermissionStatus aTTPermissionStatus = await appTrackingTransparencyPermission
.status;
if (aTTPermissionStatus == null ||
aTTPermissionStatus == PermissionStatus.denied) {
debugPrint("ATT is null or denied, requesting with retries: $retries");
aTTPermissionStatus = await appTrackingTransparencyPermission.request();
if (aTTPermissionStatus == null ||
aTTPermissionStatus == PermissionStatus.denied) {
if (retries > 0) {
await Future.delayed(Duration(milliseconds: 500));
await handleATT(retries: retries - 1);
}
else {
debugPrint(
"Warning: ATT permission request retries exhausted, aborting");
}
}
return;
}
debugPrint(
"ATT is either granted, permanently denied, limited or restricted, thus, not requesting");
}
}
}
With this code, I get this edited consent form:
Then, the following is shown when I request to display an ad:
So, to me, apart from the deprecation warnings, everything seems to work fine.
Edit 2022 06 23:
Running on iOS, I realized that the shouldShow answer is enough to know whether to show the consent form or not. Thus, the consent form is only displayed when my VPN is set to Europe or California.
Also for iOS, I added ATT handling.
I have made some other general improvements.
I do not work for Appodeal and I am not a legal expert. I just provide this code based on my personal understanding which may not lead to the right way to handle those ads and consent questions.

Flutter Facebook login responds with Http status error [500]

I have added Facebook login to my flutter project and its logging in successfully but the problem is, The user is not able to enter the home screen of the application and stays back on the login screen. It is responding as Http status error [500].
Below is the code for Facebook login/authentication:
void doFacebookSignIn() async{
print("FaceBook Clicked");
try {
final result =
await FacebookAuth.i.login(permissions: ['email']);
if (result.status == LoginStatus.success) {
final userData = await FacebookAuth.i.getUserData();
print(userData);
hitFacebookApi(result.accessToken.token);
await FacebookAuth.i.logOut();
if (result.status == LoginStatus.cancelled) {
ToastUtils.showCustomToast(context, "cancelled", Colors.white , MyColors.primaryColor);
}
if (result.status == LoginStatus.failed) {
ToastUtils.showCustomToast(context, result.message, Colors.white , MyColors.primaryColor);
}
}
} catch (error) {
print(error);
}
}
Code for entering from Login to Home screen:
void hitFacebookApi(String token) {
CommonApis().logInWithFB(
{"token": "$token"}, CommonUtils.getLanguage(context) == "english")
.then((value) async{
if (value is Map) {
String fullToken = "Bearer ${value['token']}";
ApiUtils.headerWithToken.update("Authorization",(value)=> fullToken);
await userData.save(fullToken, "client");
await userService.getProfile();
Navigator.pushAndRemoveUntil(context,PageTransition(type: PageTransitionType.fade, child: ClientMain()), (Route<dynamic> route) => false);
} else {
ToastUtils.showCustomToast(
context, value, Colors.white, MyColors.primaryColor);
print("the cause "+value);
}
});
}
Code for API method:
Future<dynamic> logInWithFB(dynamic data ,bool isEnglish) async{
try{
final response= await Dio().post("${ApiUtils.BaseApiUrl}/auth/social/facebook",data: data,options: Options(headers: ApiUtils.headerForRegister ));
if(response.statusCode==200){
return {
"token" : response.data['token']
};
}
else{
return isEnglish?response.data['error']['en']:response.data['error']['ar'];
}
}on DioError catch(e) {
if(e.response !=null) {
return e.message;
}
}
}

How to show error if server is unreachable flutter

Am still pretty new to flutter. I have a network call to be executed. But before doing that I need to check whether the device have internet connectivity and that the server is api server is reachable. I have managed to check if the internet connectivity is available, but cant show an when server is not reachable
This is what i have done so far:
login(username, password) async {
final String url = "http://10.0.2.2:8080/api/auth/signin"; // iOS
var responseJson;
try {
final response= await http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'username': username,
'password': password,
}),
);
responseJson = _response(response);
} on SocketException {
throw FetchDataException('No Internet connection');
}
print(responseJson);
SharedPreferences prefs = await SharedPreferences.getInstance();
var parse = jsonDecode(responseJson.body);
await prefs.setString('username', parse["username"]);
await prefs.setString('message', parse["message"]);
await prefs.setString('accessToken', parse["accessToken"]);
return responseJson;
}
dynamic _response(http.Response response) {
switch (response.statusCode) {
case 200:
var responseJson = json.decode(response.body.toString());
print(responseJson);
return responseJson;
case 400:
throw BadRequestException(response.body.toString());
case 401:
case 403:
throw UnauthorisedException(response.body.toString());
case 500:
throw FetchDataException(
'Error occured while Communication with Server with StatusCode : ${response
.statusCode}');
default:
throw FetchDataException(
'Error occured while Communication with Server with StatusCode : ${response
.statusCode}');
}
}
My login button function
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");
print(token);
if (token == null) {
progressDialog.hide();
showAlertsDialog(context);
} else {
showAlertzDialog(context);
}
}
},
)
Whenever I switch of the server and click on login, the app is stuck a progress bar showing signing in. How can I display an alert that there is no connection to the server?
This is how you can manage your API call.
Future<dynamic> requestGET({String url}) async {
try {
final response = await http.get(Uri.parse(url));
switch (response.statusCode) {
case 200:
case 201:
final result = jsonDecode(response.body);
final jsonResponse = {'success': true, 'response': result};
return jsonResponse;
case 400:
final result = jsonDecode(response.body);
final jsonResponse = {'success': false, 'response': result};
return jsonResponse;
case 401:
final jsonResponse = {
'success': false,
'response': ConstantUtil.UNAUTHORIZED
};
return jsonResponse;
case 500:
case 501:
case 502:
final jsonResponse = {
'success': false,
'response': ConstantUtil.SOMETHING_WRONG
};
return jsonResponse;
default:
final jsonResponse = {
'success': false,
'response': ConstantUtil.SOMETHING_WRONG
};
return jsonResponse;
}
} on SocketException {
final jsonResponse = {
'success': false,
'response': ConstantUtil.NO_INTERNET
};
return jsonResponse;
} on FormatException {
final jsonResponse = {
'success': false,
'response': ConstantUtil.BAD_RESPONSE
};
return jsonResponse;
} on HttpException {
final jsonResponse = {
'success': false,
'response': ConstantUtil.SOMETHING_WRONG //Server not responding
};
return jsonResponse;
}
}
Call this function and use response I'm calling it in init method of statefulWidget.
#override
void initState() {
// TODO: implement initState
super.initState();
final result = await requestGET('google.com');
if (result['success'] == false) {
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text(result['response']),
actions: [
FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.pop(context);
},
),
],
);
;
},
);
}
}
I think you can check the response code from the api call using http code request from this link http status code
as you can check the response from json like this:
Future<String> checkServerResponse() await
{
http.Response response =
await http.get('server_link'):
print(response.statusCode);
}
now as you can see the response code of the server based on http status code.