fluttercommunity / flutter_workmanager

A Flutter plugin which allows you to execute code in the background on Android and iOS.
859 stars 273 forks source link

🐞 `MissingPluginException` in workmanager callback method when using SharedPreferences plugin #360

Open moehajj opened 2 years ago

moehajj commented 2 years ago

Version

Technology Version
Workmanager version 0.4.1
SharedPreferences version 2.0.6

Describe the error I get the exception MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences) when trying to use the SharedPreferences plugin inside the callback method. I have only tried to get this to work on Android.

To reproduce, conveniently you can use the example application, I've tried getting it to work and it fails the same way.

Just run the app, click Start the Flutter background service -> Register OneOff Task. You will see that the callback fails, with the following output:

Launching lib/main.dart on sdk gphone x86 in debug mode...
Running Gradle task 'assembleDebug'...
Warning: Mapping new ns http://schemas.android.com/repository/android/common/02 to old ns http://schemas.android.com/repository/android/common/01
Warning: Mapping new ns http://schemas.android.com/repository/android/generic/02 to old ns http://schemas.android.com/repository/android/generic/01
Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/addon2/02 to old ns http://schemas.android.com/sdk/android/repo/addon2/01
Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/repository2/02 to old ns http://schemas.android.com/sdk/android/repo/repository2/01
Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/sys-img2/02 to old ns http://schemas.android.com/sdk/android/repo/sys-img2/01
✓  Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Debug service listening on ws://127.0.0.1:56019/nGP7bVwp-28=/ws
Syncing files to device sdk gphone x86...
D/EGL_emulation( 9695): eglCreateContext: 0xf0290cb0: maj 3 min 0 rcv 3
D/EGL_emulation( 9695): eglCreateContext: 0xf0291d50: maj 3 min 0 rcv 3
D/HostConnection( 9695): HostConnection::get() New Host Connection established 0xf0295320, tid 9761
D/HostConnection( 9695): HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_YUV_Cache ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_sync_buffer_data ANDROID_EMU_read_color_buffer_dma GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_0 
D/EGL_emulation( 9695): eglMakeCurrent: 0xf0291d50: ver 3 0 (tinfo 0xbd4e6490) (first time)
D/PathProviderPlugin( 9695): Use TaskQueues.
W/FlutterJNI( 9695): FlutterJNI.setRefreshRateFPS called more than once
W/FlutterJNI( 9695): FlutterJNI.loadLibrary called more than once
I/ResourceExtractor( 9695): Found extracted resources res_timestamp-1-1644785091935
W/FlutterJNI( 9695): FlutterJNI.prefetchDefaultFontManager called more than once
W/FlutterJNI( 9695): FlutterJNI.init called more than once
I/flutter ( 9695): simpleTask was executed. inputData = {int: 1, bool: true, double: 1.0, string: string, array: [1, 2, 3]}
I/WM-WorkerWrapper( 9695): Worker result FAILURE for Work [ id=0c5c4537-38ce-47c7-9ceb-57447620207a, tags={ be.tramckrijte.workmanager.BackgroundWorker } ]

I added a try-catch statement here to see the error, as such:

void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    switch (task) {
      case simpleTaskKey:
        print("$simpleTaskKey was executed. inputData = $inputData");
        try {
          final prefs = await SharedPreferences.getInstance();
          prefs.setBool("test", true);
          print("Bool from prefs: ${prefs.getBool("test")}");
        } catch(err) {
          print(err);
        }
        break;

Output:

Launching lib/main.dart on sdk gphone x86 in debug mode...
Running Gradle task 'assembleDebug'...
Warning: Mapping new ns http://schemas.android.com/repository/android/common/02 to old ns http://schemas.android.com/repository/android/common/01
Warning: Mapping new ns http://schemas.android.com/repository/android/generic/02 to old ns http://schemas.android.com/repository/android/generic/01
Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/addon2/02 to old ns http://schemas.android.com/sdk/android/repo/addon2/01
Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/repository2/02 to old ns http://schemas.android.com/sdk/android/repo/repository2/01
Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/sys-img2/02 to old ns http://schemas.android.com/sdk/android/repo/sys-img2/01
✓  Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Debug service listening on ws://127.0.0.1:54850/e27sXvLYKS0=/ws
Syncing files to device sdk gphone x86...
D/EGL_emulation( 9446): eglCreateContext: 0xf0292a70: maj 3 min 0 rcv 3
D/EGL_emulation( 9446): eglCreateContext: 0xf0293020: maj 3 min 0 rcv 3
D/HostConnection( 9446): HostConnection::get() New Host Connection established 0xf02a43c0, tid 9513
D/HostConnection( 9446): HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_YUV_Cache ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_sync_buffer_data ANDROID_EMU_read_color_buffer_dma GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_0 
D/EGL_emulation( 9446): eglMakeCurrent: 0xf0293020: ver 3 0 (tinfo 0xbd8e70d0) (first time)
D/PathProviderPlugin( 9446): Use TaskQueues.
W/FlutterJNI( 9446): FlutterJNI.setRefreshRateFPS called more than once
W/FlutterJNI( 9446): FlutterJNI.loadLibrary called more than once
I/ResourceExtractor( 9446): Found extracted resources res_timestamp-1-1644784374194
W/FlutterJNI( 9446): FlutterJNI.prefetchDefaultFontManager called more than once
W/FlutterJNI( 9446): FlutterJNI.init called more than once
I/flutter ( 9446): simpleTask was executed. inputData = {int: 1, bool: true, double: 1.0, string: string, array: [1, 2, 3]}
I/flutter ( 9446): MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)
I/WM-WorkerWrapper( 9446): Worker result SUCCESS for Work [ id=9a3e32db-22c9-4a8e-a610-609ac3ce7797, tags={ be.tramckrijte.workmanager.BackgroundWorker } ]
I/flutter ( 8608): MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)

You can see the I/flutter ( 8608): MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences).

Output of flutter doctor -v

 flutter doctor -v                                                                                                                            
[✓] Flutter (Channel stable, 2.8.1, on macOS 11.6.2 20G314 darwin-x64, locale en-US)
    • Flutter version 2.8.1 at /Users/username/Development/3rdparty/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 77d935af4d (8 weeks ago), 2021-12-16 08:37:33 -0800
    • Engine revision 890a5fca2e
    • Dart version 2.15.1

[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    • Android SDK at /Users/username/Library/Android/sdk
    • Platform android-32, build-tools 32.0.0
    • Java binary at: /Users/username/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/203.7935034/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2020.3)
    • Android Studio at /Users/username/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/203.7935034/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)

[✓] IntelliJ IDEA Ultimate Edition (version 2021.2.3)
    • IntelliJ at /Users/username/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] IntelliJ IDEA Ultimate Edition (version 2021.2.3)
    • IntelliJ at /Users/username/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/212.5457.46/IntelliJ IDEA.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] IntelliJ IDEA Ultimate Edition (version 2021.1.2)
    • IntelliJ at /Users/username/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/211.7442.40/IntelliJ IDEA.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] VS Code (version 1.56.2)
    • VS Code at /Users/username/Applications/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (3 available)
    • sdk gphone x86 (mobile) • emulator-5554                        • android-x86    • Android 11 (API 30) (emulator)
    • iPhone 13 Pro (mobile)  • 605EF80A-2352-4346-9BDA-243D17A682A9 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-15-2 (simulator)
    • Chrome (web)            • chrome                               • web-javascript • Google Chrome 98.0.4758.80

• No issues found!
moehajj commented 2 years ago

fwiw, the callback succeeds without any exception if I add SharedPreferences.setMockInitialValues({}); before the final prefs = await SharedPreferences.getInstance();. But that doesn't help as that's only intended to be used in testing.

ened commented 2 years ago

fwiw, the callback succeeds without any exception if I add SharedPreferences.setMockInitialValues({}); before the final prefs = await SharedPreferences.getInstance();. But that doesn't help as that's only intended to be used in testing.

This sounds similar to another issue I saw earlier in a project.

Other plugins like flutter_secure_storage work, right?

We may have a behavior in the shared prefs plug-in..

moehajj commented 2 years ago

Yes, the plugin flutter_secure_storage works fine! I'm also using sqflite and local_notifications and they work fine. It's just SharedPreferences.

Any ideas why some plugins work and others don't?

ened commented 2 years ago

Yes, the plugin flutter_secure_storage works fine! I'm also using sqflite and local_notifications and they work fine. It's just SharedPreferences.

Any ideas why some plugins work and others don't?

No idea yet & I can only offer guesses at this moment. It may have to do with the queuing process inside the Shared Pref plugin, but this does not explain why the plugin is not responding.

You are most invited to fire up the debugger for the Android side and do some digging... :)

marcjoha commented 2 years ago

Not sure if this is related, but this started to happen to me after updating my emulator to Android 12.

ened commented 2 years ago

Does it also happen on a android 11 device or emulator?

marcjoha commented 2 years ago

Ah, false alarm. I tested this on android 11 and 9 emulators, and I'm getting the same problem there.

When I updated my emulator to android 12 a while ago I jumped onto the prerelease of this library, suspect that's when this exception started happening, just that it took me a while to realize.

kuyaC commented 2 years ago

Related:

https://github.com/fluttercommunity/flutter_workmanager/issues/149 https://stackoverflow.com/questions/71115025/flutter-cant-initialize-shared-preferences-with-workmanager (same problem in iOS) http://47.57.228.104/flutter/flutter/issues/93523

I've tried a lot of things but nothing worked.

stuartmorgan commented 2 years ago

See https://github.com/flutter/flutter/issues/98473

absar commented 2 years ago

Below workaround from https://github.com/flutter/flutter/issues/98473#issuecomment-1041895729 fixes the issue

Thanks for filing this; I've filed #98591 for the general problem (which we weren't aware of when updating the plugins).

While we investigate whether we can adjust Flutter to handle this automatically in the future, here's a workaround that should allow using the current versions of the plugins:

  • Add dependencies on shared_preferences_android and shared_preferences_ios.
  • At the beginning of your background isolate entry point, add something like:
    if (Platform.isAndroid) SharedPreferencesAndroid.registerWith();
    if (Platform.isIOS) SharedPreferencesIOS.registerWith();
kuyaC commented 2 years ago

See flutter/flutter#98473

This worked for me, thank you sooo much

absar commented 2 years ago

UPDATE: This workaround https://github.com/flutter/flutter/issues/98473#issuecomment-1041895729 resolves the issue however it does not work with obfuscation. Enabling workmanager debug shows notification but actual task is not run: image

After 10 minutes shows another notification for the same task, but again actual task is not run. Note it was a one time task. Looks like workmanager keeps on trying to run the job every 10 minutes which fails hence keeps on trying to run it forever. image

Note it works fine in release mode without obfuscation.

Log:

2022-02-18 19:35:43.146 17527-20502/? E/flutter: [ERROR:flutter/shell/common/shell.cc(93)] Dart Unhandled Exception: NoSuchMethodError: No top-level getter 'Mdd' declared. Receiver: top-level Tried calling: Mdd, stack trace: Warning: This VM has been configured to produce stack traces that violate the Dart standard.


pid: 17527, tid: 20502, name Unknown isolate_dso_base: 7d52cc8000, vm_dso_base: 7d52cc8000 isolate_instructions: 7d52f50d70, vm_instructions: 7d52f4c000

00 abs 0000007d52f57d1b virt 000000000028fd1b _kDartIsolateSnapshotInstructions+0x6fab

2022-02-18 19:35:43.146 17527-20502/? E/flutter: [ERROR:flutter/runtime/dart_isolate.cc(681)] Could not resolve main entrypoint function. 2022-02-18 19:35:43.146 17527-20502/? E/flutter: [ERROR:flutter/runtime/dart_isolate.cc(165)] Could not run the run main Dart entrypoint. 2022-02-18 19:35:43.148 17527-20502/? E/flutter: [ERROR:flutter/runtime/runtime_controller.cc(381)] Could not create root isolate. 2022-02-18 19:35:43.148 17527-20502/? E/flutter: [ERROR:flutter/shell/common/shell.cc(580)] Could not launch engine with configuration.

absar commented 2 years ago

@ened can you look into above comment, or do you want me to create a new issue?

HamidMusayev commented 2 years ago

Any news or update? 😪

absar commented 2 years ago

All of you, who are impacted, should give a thumbs up on this issue https://github.com/flutter/flutter/issues/98591 so that it gets prioritized, as MissingPluginException issue is impacting all plugins which are moving to "in-package method channel", same issue is now happening with path_provider (path_provider_android 2.0.12 to be specific) Note, it's not going to solve the obfuscation issue, which is a separate issue.

sarbagyastha commented 2 years ago

flutter/flutter#98475

rafaelsetragni commented 2 years ago

Ive created the Awesome Notification's plugin, and im trying to do the same as you: Create a parallel flutter engine to run dart code while the app is terminated.

What I'm coming to the conclusion that on iOS, the plugins are not getting register on the beginning, as the same on Android.

Currently, im trying to do it calling the method GeneratedPluginRegistrant.register(with: flutterEngine!), but im not getting visibility inside the background class, as your BackgroundWorker.swift.

rafaelsetragni commented 2 years ago

I created a issue thread in flutter to discuss possible solutions to this. https://github.com/flutter/flutter/issues/99883

Aturex1 commented 10 months ago

Same problem here, with shared_preferences.

The workaround doesn't work on Linux, so Linux solutions are appreciated.