Firebase remote config not updating and using older value+ Flutter - flutter

When we have a higher version available on the play store. This feature redirects users to the app store to install updates. But it is not working on a few devices. The user still using the older version. If the user clears the storage then an alert is displayed. We can not ask our users to clear storage. Any help would be greatly appreciated.
#override
void initState() {
super.initState();
try {
versionCheck(context);
} catch (e) {
print(e);
}
}
versionCheck(context) async {
//Get Current installed version of app
final PackageInfo info = await PackageInfo.fromPlatform();
double currentVersion =
double.parse(info.version.trim().replaceAll(".", ""));
//Get Latest version info from firebase config
final FirebaseRemoteConfig remoteConfig =
await FirebaseRemoteConfig.instance;
try {
// Using default duration to force fetching from remote server.
await remoteConfig.fetch();
await remoteConfig.fetchAndActivate();
remoteConfig.getString('force_update_current_version');
double newVersion = double.parse(remoteConfig
.getString('force_update_current_version')
.trim()
.replaceAll(".", ""));
if (newVersion > currentVersion) {
_showVersionDialog(context);
}
} on Exception catch (exception) {
// Fetch throttled.
print(exception);
} catch (exception) {
print('Unable to fetch remote config. Cached or default values will be '
'used');
}
}
When I tried to print the values I am getting the same values new:160.0 current:160.0, clearing the storage of the app from the setting displays the alert.

I think your code in general looks right to me. Though there is a redundant line:
remoteConfig.getString('force_update_current_version');
But this should be fine.
What I am concerned about is that you replace all your . with empty and convert the version to a number. This can result in a bug if there are two versions like:
1.21.4 vs 1.2.15. The first one is supposed to be newer, but the code will get 1214 > 1215 is false

Related

Login with facebook works on real phones but not emulators, it started happening with the new emulator update

This code works on real phones but not on emulators
I use flutter_facebook_auth. This exact code worked fine before emulator update and it's still works on real devices, but on emulator it just do nothing after coming back from fb login page.
static Future<User?> signInWithFacebook() async {
try {
//Trigger the sign-in flow
final LoginResult loginResult =
await FacebookAuth.instance.login(permissions: [
'public_profile',
'email',
'user_friends',
]);
if (loginResult.status == LoginStatus.success) {
print('success');
facebookAuthCredential =
FacebookAuthProvider.credential(loginResult.accessToken!.token);
print(loginResult.accessToken?.token);
Credential = await FirebaseAuth.instance
.signInWithCredential(facebookAuthCredential);
print('here 1');
UserData = await FacebookAuth.instance.getUserData(
fields:
"name,email,picture.width(400),birthday,friends,gender,link");
print(UserData);
} else {
print(loginResult.message);
error = loginResult.message!;
}
user = Credential.user;
await user
?.updatePhotoURL(UserData['picture']['data']['url'])
.then((value) {
print('success' + UserData['picture']['data']['url']);
});
return Credential.user;
} on FirebaseException catch (e) {
error = e.code;
print(e.code);
}
}
}
In the above code the app flow stops or freezes on
Credential = await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
What I have tried is:
Tried other emulators, different api's and models.
I tried adding new release and debug keyhashes to both facebook and firebase
I tried increasing emulator ram and cpu cores etc
I tried refreshing fb sdk and json and other dev dependencies
I tried flutter clean
I tried Invalidate Caches
I uninstalled android studio and all of it's components and install again
Is this happening with just me or it's a bug in the new emulator update?
It's been 12 hours, can somebody please help and check if their updated emulator is working with fb login
I solved it by downgrading emulator version to 31.2.9,
Here is emulator_archive how you can do it:

Flutter - How to save a file requesting permission with Permission Handler if my code is deprecated?

I'm new to Flutter and I've been following this tutorial but it's from 2020 and I know a lot of things have changed.
I want to save a file on my local phone and apparently I need to ask permission to do so. I'm not sure if checking the platform is still needed or not.
I don't want to run the --no-sound-null-safety command.
This is the only part that I wasn't able to update by myself.
_save() async {
if (Platform.isAndroid) {
await _askPermission();
}
var response = await Dio().get(widget.imgUrl!,
options: Options(responseType: ResponseType.bytes));
final result =
await ImageGallerySaver.saveImage(Uint8List.fromList(response.data));
print(result);
Navigator.pop(context);
}
_askPermission() async {
if (Platform.isIOS) {
await PermissionHandler().requestPermissions([PermissionGroup.photos]);
} else {
await PermissionHandler().checkPermissionStatus(PermissionGroup.storage);
}
}
The _save method seems alright but I wonder if there's something to update there as well.
The _askPermission method is the one that I need help with.

can't load iap products in local, it waits forever

I'm using the official in_app_purchase plugin, version ^1.0.4, and I'm following the official guide from Google insert my first iap (https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases#0).
My consumable iap product is active on Play console with name "pacchetto_25", I've already submitted to the alpha channel my app and is accepted, the tester email is correctly configured in the Tester Group and in Licence Testing.
Now I'm trying to load the iap products in my app, the code is the same of the guide:
Future<void> loadPurchases() async {
final available = await _iap.isAvailable();
if (!available) {
print("STORE NOT AVAILABLE");
return;
} else {
print("STORE AVAILABLE");
const ids = <String>{
"pacchetto_25",
};
final response = await _iap.queryProductDetails(ids);
response.notFoundIDs.forEach((element) {
print('Purchase $element not found');
});
response.productDetails.forEach((element) {
print("Purchase $element found");
});
// products =
// response.productDetails.map((e) => PurchasableProduct(e)).toList();
}
}
In my console I have the "STORE AVAILABLE" message, but then nothing else. If I put same debug point it does not stops on them, this problem appear after this line:
final response = await _iap.queryProductDetails(ids);
Do someone know what's happening? I've no errors in my console and the code after loadPurchases() is not executed, it's like is waiting forever... Any ideas?
Solved! If you have the same issue DON'T put
implementation("com.android.billingclient:billing:4.0.0")
in your build.gradle

Flutter - Health package not loading STEP data

I've used health-3.0.3 in my flutter application to get the Google fit data. I'm able to get every data other than STEP-data which shows zero always.
You can refer to the health package here
Health 3.0.3 Flutter
This is the code block to access the STEP datatype in my application
List<HealthDataType> types = [
HealthDataType.STEPS,
HealthDataType.WEIGHT,
//HealthDataType.HEIGHT,
];
setState(() => _state = AppState.FETCHING_DATA);
/// You MUST request access to the data types before reading them
bool accessWasGranted = await health.requestAuthorization(types);
double steps = 0;
if (accessWasGranted) {
try {
/// Fetch new data
List<HealthDataPoint> healthData =
await health.getHealthDataFromTypes(startDate, endDate, types);
/// Save all the new data points
_healthDataList.addAll(healthData);
} catch (e) {
print("Caught exception in getHealthDataFromTypes: $e");
}
/// Filter out duplicates
_healthDataList = HealthFactory.removeDuplicates(_healthDataList);
/// Print the results
_healthDataList.forEach((x) {
print("Data point: $x");
steps += (x.value as double);
});
print("Steps: $steps");
You can refer to the full code under the examples tab in the given link. Does anyone know what's wrong here?
health: 3.0.4 is more stable, when I'm writing this answer.
From Android 10. you have to add ACTIVITY_RECOGNITION for getting STEP Count permission in AndroidManifest.xml.
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
And then using permission_handler ask for permission.
if (Platform.isAndroid) {
final permissionStatus = Permission.activityRecognition.request();
if (await permissionStatus.isDenied ||
await permissionStatus.isPermanentlyDenied) {
showToast(
'activityRecognition permission required to fetch your steps count');
return;
}
}

Flutter getting an exception when calling queryPastPurchases (in_app_purchase plugin): Cannot find receipt for the current main bundle

I'm trying to utilise the in_app_purchase plugin (https://pub.dev/packages/in_app_purchase) for my Flutter App.
Calling a queryProductDetails(ids) works just fine,
but when calling the queryPastPurchases() I get the following exception:
PlatformException (PlatformException(storekit_no_receipt, Cannot find receipt for the current main bundle., null))
Seems like this is the source for the exception:
https://github.com/flutter/plugins/blob/master/packages/in_app_purchase/ios/Classes/FIAPReceiptManager.m
Worth mentioning:
I've setup an IAP in App-Store-Connect.
This IAP hasn't been sent for Apple approval yet.
App is in development, tested using TestFlight with beta testers.
Another issue is that this exception doesn't get cought in the try-catch statement (see code below), but only by the environment when checking the "All Exceptions" option in VSCode...
Tested on Emulator and real device.
[UPDATE]:
Added a breakpoint to the objective-c code of the plugin, and saw that the receiptURL refers to "sandboxReceipt". So maybe it's because I don't use sandbox users?
Future<void> _getPastPurchases() async {
try {
final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.instance.queryPastPurchases();
if (response.error != null) {
// Handle the error
print(response.error.toString());
}
print('response = ' + response.toString());
for (PurchaseDetails purchase in response.pastPurchases) {
if (Platform.isIOS) {
//InAppPurchaseConnection.instance.completePurchase(purchase);
}
}
setState(() {
_purchases = response.pastPurchases;
});
} on PlatformException catch(err) {
print(err.toString());
}
catch (err) {
print(err.toString());
}
}