fluttercommunity / flutter_workmanager

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

🐞[Cannot register OneOffTask iOS] #357

Open saad197 opened 2 years ago

saad197 commented 2 years ago

Version

Technology Version
Workmanager version 0.5.0-dev.8
Xcode version 13.2.1
Swift version 5.5.2-dev
iOS deployment target 13.0

Describe the error I am not able to schedule OneOff task on iOS. I can only do it if I through debug, "Simulate background fetch" which gets me

2022-02-01 01:09:06.770562-0700 Runner[15798:4641652] flutter: notifications set ios 2022-02-01 01:09:06.853857-0700 Runner[15798:4640548] [workmanager.BackgroundWorker] performBackgroundRequest(_:) -> performBackgroundRequest.newData (finished in 0.48 seconds)

I know everything is set up correctly because simulation would not work otherwise...

The same issue on Workmanager 0.4.1 except, here is the interesting part, 0.4.1 would give me this error when I would register my task

PlatformException(unhandledMethod("registerOneOffTask") error, Unhandled method registerOneOffTask, null, null) #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7) #1 MethodChannel._invokeMethod

This error no longer occurs on prerelease 0.5.0-dev.8, but still not scheduling the task. I also cannot schedule the task on the sample app provided.

I tested this on my physical iPhone 11 (iOS 15.2.1).

Output of flutter doctor -v

[✓] Flutter (Channel stable, 2.8.1, on macOS 12.1 21C52 darwin-x64, locale en-CA) • Flutter version 2.8.1 at /users/saad/Documents/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 77d935af4d (7 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 30.0.3) • Android SDK at /Users/saad/Library/Android/sdk ✗ cmdline-tools component is missing Run path/to/sdkmanager --install "cmdline-tools;latest" See https://developer.android.com/studio/command-line for more details. ✗ Android license status unknown. Run flutter doctor --android-licenses to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.

[✓] 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 /Applications/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)

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

Iam-that-Chic commented 2 years ago

following, i have the same error too.

cormalenv commented 2 years ago

I'm a bit confused by this. Is it actually possible to register one of tasks on iOS? I was under the impression this is an Android only function as described in the ReadMe (although I note the example triggers registerOneOffTask via a platform enable iOS button?!?).

The API states that once Workmanager is initialised you can then registerOneOffTask or registerPeriodTask for Android whereas " iOS periodic task is automatically scheduled". The API therefore appears consistent with the tasking specifications for iOS. iOS is very strict in controlling timings of the 3 available BG tasking options; AppRefresh, Processing and URLSession. As I understand Workmanager utilises Processing for which triggering is ultimately out of the developers hands, generally occurring during times of low device use eg when the device is on charge.

I am still not sure why the example includes a registerOneOffTask then. Is this simply a Processing task with a callback to self cancel? Sorry if I have confused this further.

@ened have I missed something here?

EDIT: My results on Example app. Simulating a background task though Xcode runs fine. OneOffTask gives error as below.

OneoffTask Error in Example 2022-02-05 22:44:45.770103+1100 Runner[3306:37221] [VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: PlatformException(bgTaskSchedulingFailed(Error Domain=BGTaskSchedulerErrorDomain Code=1 "(null)") error, Scheduling the task using BGTaskScheduler has failed. This may be due to too many tasks being scheduled but not run. See the error for details: Error Domain=BGTaskSchedulerErrorDomain Code=1 "(null)"., null, null) #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7) #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:18) #2 Workmanager.registerOneOffTask (package:workmanager/src/workmanager.dart:186:7)
Flutter Doctor [✓] Flutter (Channel stable, 2.5.3, on macOS 11.4 20F71 darwin-arm, locale en-AU) • Flutter version 2.5.3 at .../Library/Flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 18116933e7 (4 months ago), 2021-10-15 10:46:35 -0700 • Engine revision d3ea636dc5 • Dart version 2.14.4 [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0) • Android SDK at .../Library/Android/sdk • Platform android-31, build-tools 31.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7772763) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 13.1, Build version 13A1030d • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2021.1) • Android Studio at /Applications/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.11+0-b60-7772763) [✓] Connected device (2 available) • iPhone 13 mini (mobile) • D12A97B4-6173-4705-82DD-126F7A9EE754 • ios • com.apple.CoreSimulator.SimRuntime.iOS-15-0 (simulator) • Chrome (web) • chrome • web-javascript • Google Chrome 97.0.4692.99 • No issues found!
saad197 commented 2 years ago

Yes so currently it is impossible to register anything on iOS, so workmanager basically does not work. The only way to register the task is through simulation. Without that nothing ever happens. Even when registered through simulation, the task is never triggered again, only once when simulated.

orestesgaolin commented 2 years ago

Interestingly there's entry in flutter log indicating that the given task was received, for instance for id 1111 the log says:

flutter: Received 1111
cormalenv commented 2 years ago

@saad197 IMHO sort of....

From what I can tell forget timed scheduling/one of tasks in iOS. Initialising the background service and handing off to the OS is all that can be achieved. This isn't a workmanager specific issue this is all about iOS. All workmanager can do is provide a method to support either BGAppRefreshTask or BGProcessingTask. Once this is done it is over to the OS to schedule and your app must be developed to cope with as much.

If you put aside any notion about achieving set intervals , workmanager does appear to function correctly within the boundaries of iOS (oneOffTasks aside). Initialising the service and simulating a background fetch works fine. The plugin uses BGProcessingTask (as far as I can tell), so getting the task to run outside of simulation is another story. To find out more about how your BGProcessingTask is managed and scheduled in the real world skip through to 15:00 in this video from apple.

The documentation probably doesn't spell this out enough and there appear some contradictions that need to be cleared up.

It's clearly a confusing topic and seeing semi-regular periodic tasks work fine on Android doesn't help. The background_fetch plugin tries to clarify this a bit better. Incidentally it promotes the use of BGAppRefreshTask and suggests that BGProcessingTask is bit of hit and miss, almost recommending not to use it but each have their place. You just need to determine what suits your purpose and develop to cope with the boundaries imposed by iOS.

I say all this IMHO. I am very happy to be corrected.

saad197 commented 2 years ago

@cormalenv so my question is how do I make the plugin work at all with iOS? Because as stated even when initialized without any errors it does not actually register or execute the task, ever. I tested this on my physical iPhone.

cormalenv commented 2 years ago

@cormalenv so my question is how do I make the plugin work at all with iOS? Because as stated even when initialized without any errors it does not actually register or execute the task, ever. I tested this on my physical iPhone.

@saad197 How long did you let it run on the physical device? I have found it can take a day or two for iOS to analyse use patterns before it settles on appropriate timings and kicks off the first execution.

EDIT: I ran the example for 3 days on a physical with no triggering :(. So you seem to be right. I'll run the same with the background_fetch schedule task (ie using BGProcessingTask) to see if there are different results there. Worth noting the following from their documentation.

To be honest I've switched iOS over background_fetch with BGAppRefresh for now as I needed to get my app out. AppRefresh it not the right option for my use case but until this is sorted it is working at least partially. I've retained workmanager on Android as it's been pretty flawless for a number of years.

rackberg commented 2 years ago

Hello there,

we faced the same issue you've described and discussed above.

After digging into the code and also reading through the ios code of the provided example app we noticed that the documentation in the README file is missing a very important step for the ios setup.

Insert this in your AppDelegate of your flutter app:

WorkmanagerPlugin.setPluginRegistrantCallback { registry in
    // Registry in this case is the FlutterEngine that is created in Workmanager's
    // performFetchWithCompletionHandler or BGAppRefreshTask.
    // This will make other plugins available during a background operation.
    GeneratedPluginRegistrant.register(with: registry)
}

For reference: This code is from the AppDelegate of the example app.

For every task identifier registered under the key BGTaskSchedulerPermittedIdentifiers in your app Info.plist file add the following line of code to the AppDelegate:

For demonstration purpose we assume that the task e.g. "my.task" is set in the Info.plist file:

WorkmanagerPlugin.registerTask(withIdentifier: "my.task")

After doing that the callbackDispatcher you used in the Workmanager().initalize() method should be called when you execute the background fetch simulation of xCode under "Debug" > "Simulate Background Fetch"

This should immediately execute the background task while debugging with xCode.

ened commented 2 years ago

Please add a PR for missing docs

ghost commented 2 years ago

Not working @rackberg

 type 'WorkmanagerPlugin' has no member 'registerTask'
ghost commented 2 years ago

Didn't know where to put

SystemCapabilities = {
    com.apple.BackgroundModes = {
        enabled = 1;
    };
};

project.pbxproj had more than 4800 lines.

leonus96 commented 2 years ago

Didn't know where to put

SystemCapabilities = {
  com.apple.BackgroundModes = {
      enabled = 1;
  };
};

project.pbxproj had more than 4800 lines.

It was not necessary for me 🤷🏻‍♂️

KirioXX commented 2 years ago

Hi, I see similar behaviour on the example app. registerOneOffTask is doing nothing, but when I trigger "Simulate background fetch" the app crashes with these logs:

2022-08-23 09:58:10.185987+0100 Runner[2719:70633] Metal API Validation Enabled
2022-08-23 09:58:10.483265+0100 Runner[2719:70872] flutter: The Dart VM service is listening on http://127.0.0.1:58076/C7PhGHlkerc=/
2022-08-23 09:59:05.105665+0100 Runner[2719:71113] flutter: The iOS background fetch was triggered
2022-08-23 09:59:05.111667+0100 Runner[2719:71113] flutter: You can access other plugins in the background, for example Directory.getTemporaryDirectory(): /var/mobile/Containers/Data/Application/AA9E7604-3B91-4B80-A7B9-A49CCBE39E28/Library/Caches
2022-08-23 09:59:05.280439+0100 Runner[2719:70633] [workmanager.BackgroundWorker] performBackgroundRequest(_:) -> performBackgroundRequest.newData (finished in 0.47 seconds)

My system:

My test device:

flutter doctor -v output:

[✓] Flutter (Channel stable, 3.0.5, on macOS 12.5.1 21G83 darwin-x64, locale en-GB)
    • Flutter version 3.0.5 at /Users/___/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f1875d570e (6 weeks ago), 2022-07-13 11:24:16 -0700
    • Engine revision e85ea0e79c
    • Dart version 2.17.6
    • DevTools version 2.12.2

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at /Users/___/Library/Android/sdk
    • Platform android-32, build-tools 31.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
    • All Android licenses accepted.

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

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

[✓] Android Studio (version 2021.1)
    • Android Studio at /Applications/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.11+0-b60-7590822)

[✓] VS Code (version 1.70.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.46.0

[✓] Connected device (1 available)
    • My iPad (mobile) • 2783e9a7ba84ac8449beef783bd2d872ea5272f6 • ios            • iOS 15.6.1 19G82

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

Is there something I could miss in the setup or should the example work out of the box?

teenrage-dev commented 5 months ago

Do you have any updates?