Flutter: can't initialize shared preferences with workmanager

615

This is due to a change in the implementation of shared_preferences, see this issue for discussion.

For now you can manually run the plugin's Dart registration before using it in an isolate:

if (Platform.isAndroid) SharedPreferencesAndroid.registerWith();
if (Platform.isIOS) SharedPreferencesIOS.registerWith();

You will need to add direct dependencies on shared_preferences_android and shared_preferences_ios to use those classes.

Share:
615
Cedric
Author by

Cedric

📸@dev_pogi

Updated on December 01, 2022

Comments

  • Cedric
    Cedric over 1 year

    As the title say, I'm using 2 plugins, workmanager and shared preferences. The workmanager part works as it's supposed to, while I get an error from shared preferences.

    This is part of my code which has to do with the workmanager plugin:

    void callbackDispatcher() {
      Workmanager().executeTask((taskName, inputData) async {
        switch (taskName) {
          case 'midnight_task':
            try {
              await SharedPrefsHelper().initSharedPrefsInstance(); //THIS line causes the error
              await PedometerService.midnightTask();
              print('workmanager_service.dart: looks like midnightTask got successfully executed :D');
            } catch (e) {
              print('workmanager_service.dart midnightTask error: $e');
            }
            break;
          default:
            print('workmanager_service.dart callbackDispatcher(): unhandled taskName: $taskName');
        }
        return Future.value(true); // "The task is successful"
      });
    }
    

    This is part of my code which deals with shared preferences:

    SharedPreferences _prefs;
    
      Future<void> initSharedPrefsInstance() async {
        print('initSharedPrefsInstance()');
        if (_prefs == null) _prefs = await SharedPreferences.getInstance(); //the error gets thrown here
        print('shared prefs initialized()');
      }
    
      
      //this will NOT persist data
      Future<void> initSharedPrefsInstanceMock() async {
        print('initSharedPrefsInstanceMock()');
        SharedPreferences.setMockInitialValues({}); //<- this line: only difference to above method
        if (_prefs == null) _prefs = await SharedPreferences.getInstance();
        print('initSharedPrefsInstanceMock: shared prefs initialized()');
      }
    

    The following error gets thrown at the line specified by the comment: workmanager_service.dart midnightTask error: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences).

    I've tried this from another stackoverflow question (second method in the previous code sample) and it does NOT throw the error then, but as that guy said, it doesn't persist data so it's useless. I've also tried the other things he suggested (editing /android/app/build.gradle), and also many other things suggested by other people, but nothing worked for me.

    Does anyone know what I can do to solve this problem?

  • Cedric
    Cedric about 2 years
    I did this and it works (almost), but I have a problem: The data that I set in shared_preferences from my normal code and from my workmanager-code are not consistent with each other. In Device Manager I can look at the file FlutterSharedPreferences.xml and that appears to show the values saved by workmanager with shared_preferences. But in my normal code, if I want to access values from shared_preferences, they are different. (and I used SharedPreferencesAndroid.registerWith(); both times to initialize) Do you know how to solve this?
  • smorgan
    smorgan about 2 years
    @Cedric shared_preferences caches preferences on the Dart side. If you want to read changes that weren't made through the same instance of the plugin class (like from a separate copy in another isolate) you have to reload()
  • smorgan
    smorgan about 2 years
    "I used SharedPreferencesAndroid.registerWith(); both times to initialize" -> there is no reason to do this in the non-isolate code.
  • smorgan
    smorgan about 2 years
    @aaronvargas That's expected; those versions are the ones right before the changes that added the Dart implementations (which is what doesn't work automatically in the isolate and needs to be called manually). You shouldn't have the issue described here with those versions in the first place.
  • stranger_cool
    stranger_cool almost 2 years
    @smorgan I tried this but I'm having error about 'PlatformException (PlatformException(channel-error, Unable to establish connection on channel., null, null))'. Do you have idea how to solve this ?