1

enter image description here

there are two ways to exit from our Android (Flutter) app, we can press back button repeatedly or we can just press home button

if a user press home button (not back button), then the app will be in the background. and I send FCM (Firebase Cloud Messaging) push notification to users, and the app will receive the message in background handler. and then I save a string in the shared preference like this

Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString("myKey", "value here");
  
  final testValue = prefs.getString("myKey");
  print("value in background handler: $testValue");  // I confirm I can get the saved value here
}

as you can see from the code above, I can get the value from the shared preference in firebaseMessagingBackgroundHandler

after receiving push notification, the user will open the app and it will directly open the home page.

In the home page, I try to get the value I saved before

  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance?.addPostFrameCallback((_) async {

      final prefs = await SharedPreferences.getInstance();
      final savedValue = prefs.getString("myKey");
      print(savedValue); // I get null here initially

    });
  }

as you can see, I get null value when I go back directly to the app. I have to exit the app again using back button and then eventually I can get the string value from shared preference.

why I have to press back button to get the value from shared preference? how to solve this?

Alexa289
  • 8,089
  • 10
  • 74
  • 178
  • Just because you are getting `print("value in background handler: $testValue"); ` to print the value does not mean that it's been saved in local storage. It's most likely the case that the developer is saving the data on some collection in RAM so that you don't have to load it up from disk during the life of the app. Basically this means that for whatever reason (probably some limitation on the part of the OS) that IO operation isn't carried out, and if you read the docs on shared preferences there is a note on reliability. – moneer alhashim Oct 10 '21 at 09:41
  • @Alexa289 did you find the solution ? – Hunt Jan 10 '22 at 10:06

1 Answers1

0

initState executes once, before the widget is built for the first time. If you put the app to the background and then you open it again, initState will not run again.

(Not part of your question, but even if you want to read something from Shared Preferences before the first build, initState is not a really good place for it, since it can't be async, that is why you use addPostFrameCallback. I would rather suggest using for example a FutureBuilder in your build method, so that you can await the result of the async operation, if you need the result from it for the build.)

So your value is probably saved to Shared Preferences, but you need to find another way to read it. If you want to detect when your app is resumed from the background, you can do it by watching app life cycle changes, see for example in this article.

But I think there is an easier way, if you want to get the notification data when the user clicks on a notification during your app is in the background. You can listen to onMessageOpenedApp and then you can get the message directly in your code without Shared Preferences:

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
  
});
Peter Koltai
  • 8,296
  • 2
  • 10
  • 20
  • yes the initState will only be called once, but the code inside `addPostFrameCallback` can be executed multiple times, my home page is located in the index 0 in my bottom nav bar, so if I change from tab 0 to tab 1 and to tab 0 again, the `addPostFrameCallback` will be executed again – Alexa289 Oct 11 '21 at 05:03
  • unfortunately it will be the same if change it to onResume callback :( – Alexa289 Oct 11 '21 at 05:03
  • Thank you very much Peter. but I also can't implement it on `onMessageOpenedApp` since I am trying to make a 'silent update' using FCM, no push notification display. – Alexa289 Oct 11 '21 at 05:10
  • Ok, I misunderstood, you wrote "after receiving push notification, the user will open the app", I thought it meant clicking on the notification. – Peter Koltai Oct 11 '21 at 06:24