Appodeal Consent Manager won't show - flutter

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.

Related

how to detect connection in flutter

so i have this function which detect if there is connection or not . if yes the var activeConnection is true else false . So if the connection is working i'm going to call a method sendEmail() which work with the plugin mailer . My problem is when i activated the WIFI it can send the email then if i turn it off an exception is shown
E/flutter ( 5347): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)]
Unhandled Exception: SocketException: Failed host lookup:
'smtp.gmail.com' (OS Error: No address associated with hostname, errno
= 7)
in this case activeConnection is true but when it try to send the email it can't find the connection . if i turn off the wifi and wait for a moment before i send the email it can detect that there is no wifi so i tried to add a sleep function before it check the connection but i'm facing the same problem .
this is the code :
Future checkUserConnection() async {
try {
//sleep(const Duration(seconds: 10));
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
setState(() {
activeConnection = true;
print(activeConnection);
});
}
} on SocketException catch (_) {
setState(() {
activeConnection = false;
print(activeConnection);
});
}
//print(activeConnection);
}
and this is where i call my function
onTap: () {
checkUserConnection();
print(activeConnection);
if (activeConnection) {
sendEmail();
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
false, "email sended ", Icons.error_outline));
} else {
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
true,
"check your internet connection !!!",
Icons.error_outline));
}
print("hello");
},
You have to make async function like this:
Future<bool> checkUserConnection() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
} on SocketException catch (_) {
return false;
}
}
After that onTap() you have to code like this:
onTap: () {
checkUserConnection().then((activeConnection){
if (activeConnection) {
sendEmail();
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
false, "email sended ", Icons.error_outline));
} else {
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
true, "check your internet connection !!!",
Icons.error_outline));
}
});
}

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;
}
}
}

MissingPluginException in my flutter code - NetworkInfo().getLocationServiceAuthorization()

I've written a Class to handle network connection.
I need because my app works only in a specific environment so I want to check the wifi SSID.
I use the connectivity package to check if I'm connected to WIFI.
I want to use the network_info_plus package to read the wifi SSID name, but it throws this exception:
MissingPluginException (MissingPluginException(No implementation found for method getLocationServiceAuthorization on channel dev.fluttercommunity.plus/network_info))
My code is the following:
import 'dart:async';
import 'package:network_info_plus/network_info_plus.dart' as info;
import 'package:connectivity/connectivity.dart';
import 'package:flutter/services.dart';
enum ConnectivityStatus { Connected, NotConnected }
class ConnectivityService {
// Create our public controller
StreamController<ConnectivityStatus> connectionStatusController =
StreamController<ConnectivityStatus>();
ConnectivityService() {
// Subscribe to the connectivity Chanaged Steam
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
// Use Connectivity() here to gather more info if you need t
connectionStatusController.add(_getStatusFromResult(result));
});
}
// Convert from the third part enum to our own enum
ConnectivityStatus _getStatusFromResult(ConnectivityResult result) {
switch (result) {
case ConnectivityResult.mobile:
return ConnectivityStatus.NotConnected;
case ConnectivityResult.wifi:
_initNetworkInfo();
return ConnectivityStatus.Connected;
case ConnectivityResult.none:
return ConnectivityStatus.NotConnected;
default:
return ConnectivityStatus.NotConnected;
}
}
}
Future<String?> _initNetworkInfo() async {
String? wifiName;
final _networkInfo = info.NetworkInfo();
try {
var status = await _networkInfo.getLocationServiceAuthorization();
if (status == info.LocationAuthorizationStatus.notDetermined) {
status = await _networkInfo.requestLocationServiceAuthorization();
}
if (status == info.LocationAuthorizationStatus.authorizedAlways ||
status == info.LocationAuthorizationStatus.authorizedWhenInUse) {
wifiName = await _networkInfo.getWifiName();
} else {
wifiName = await _networkInfo.getWifiName();
}
} on PlatformException catch (e) {
print(e.toString());
wifiName = 'Failed to get Wifi Name';
}
return wifiName;
}
EDIT: I decided to create a class to handle the retrieval of wifi name:
...
case ConnectivityResult.wifi:
if (NetworkInfo().wifiName == 'WIFI_SSID_NAME') // !!! HANDLE ASYNC
return ConnectivityStatus.Connected;
else
return ConnectivityStatus.NotConnected;
...
class NetworkInfo {
String? wifiName;
NetworkInfo() {
_initNetworkInfo();
}
Future<void> _initNetworkInfo() async {
String? wifiName;
final _networkInfo = info.NetworkInfo();
try {
var status = await _networkInfo.getLocationServiceAuthorization();
if (status == info.LocationAuthorizationStatus.notDetermined) {
status = await _networkInfo.requestLocationServiceAuthorization();
}
if (status == info.LocationAuthorizationStatus.authorizedAlways ||
status == info.LocationAuthorizationStatus.authorizedWhenInUse) {
wifiName = await _networkInfo.getWifiName();
} else {
wifiName = await _networkInfo.getWifiName();
}
} on PlatformException catch (e) {
print(e.toString());
wifiName = 'Failed to get Wifi Name';
}
this.wifiName = wifiName;
}
}
The getLocationServiceAuthorization is only for iOS so if you are coding for Android too, you should split them into separate blocks:
final _networkInfo = info.NetworkInfo();
try {
//may throw on non-iOS platforms
var status = await _networkInfo.getLocationServiceAuthorization();
if (status == info.LocationAuthorizationStatus.notDetermined) {
status = await _networkInfo.requestLocationServiceAuthorization();
}
} on PlatformException catch (e) {
print(e.toString());
wifiName = 'Failed to verify authorization';
}
try {
wifiName = await _networkInfo.getWifiName();
} on PlatformException catch (e) {
print(e.toString());
wifiName = 'Failed to get Wifi Name';
}
Also inside /android/app/build.gradle you should insert:
shrinkResources false
minifyEnabled false
in the buildTypes/release block:
buildTypes {
release {
shrinkResources false
minifyEnabled false

How to access dio onResponse.statuscode in catch code

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');
}

Sign in with Facebook Flutter, how can I change my code?

How can I change my code below so I can login with Facebook? The second method is just normal login, but I want apply the same app login logic to the Facebook login.
// facebook login
bool isLoggedIn = false;
void onLoginStatusChanged(bool isLoggedIn) {
setState(() {
this.isLoggedIn = isLoggedIn;
});
}
void initiateFacebookLogin() async {
var facebookLogin = FacebookLogin();
var facebookLoginResult = await facebookLogin.logIn(['email']);
switch (facebookLoginResult.status) {
case FacebookLoginStatus.error:
print("Error");
onLoginStatusChanged(false);
break;
case FacebookLoginStatus.cancelledByUser:
print("CancelledByUser");
onLoginStatusChanged(false);
break;
case FacebookLoginStatus.loggedIn:
print("LoggedIn");
onLoginStatusChanged(true);
break;
}
}
// application login
void login() async {
if (loginFormKey.currentState.validate()) {
loginFormKey.currentState.save();
repository.login(user).then((value) {
//print(value.apiToken);
if (value != null && value.apiToken != null) {
scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text(S.current.welcome + value.name),
));
Navigator.of(scaffoldKey.currentContext)
.pushReplacementNamed('/Pages', arguments: 2);
} else {
scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text(S.current.wrong_email_or_password),
));
}
});
}
}