In this section, we’ll highlight the most important information about background execution on Flutter.

For more information about how the Flutter WorkManager package works internally, please keep reading.

If you just want to get started with the package you can scroll to the bottom of the page.

How to schedule a background job in Dart?

Let’s first take a look at how we would do this without Flutter.

Android and iOS have very different approaches:

On Android, there are multiple ways to schedule a background job. It seems like every year there is a new and better way :

AlarmManager

JobService

Firebase Job Dispatcher

and the latest one, WorkManager.

The consensus these days seems to be on WorkManager.

Long story short: WorkManager provides an easy-to-use API where you can define:

If a background job should run once , or periodically

, or Apply multiple constraints like for example if a task needs internet connection, or if the battery should be fully charged, and so much more.

like for example if a task needs internet connection, or if the battery should be fully charged, and so much more. An interval of how many times a job should run.

The job is guaranteed to run some time in the future.

Android takes full ownership of when is the best time to run background jobs, and batches these jobs (our app’s and others’) together for minimum battery drain.

If you want to learn more about WorkManager, have a look the excellent documentation.

iOS

On iOS, options are much more limited. The systems decides when to give an app the chance to perform a background fetch, so that the app appears to remain “alive”.

The only control we have is the minimum background fetch interval, but iOS may decide to never start our app to perform a background fetch (for example if we take too long before returning a UIBackgroundFetchResult to the completionHandler).

Starting Flutter Engine in the background

When a background job is started by native the Flutter engine is not active. So we are unable to run Dart.

Can Android/iOS starts the Flutter engine in the background?

Yes! We’ll first need to register a Dart callback function which will only be invoked whenever a background job is started by the native code.

This callback function is referred to as a callbackDispatcher.

The process is the following on Dart:

📝 Note: The callbackDispatcher must be a top level function or a static function.

The PluginUtilities#getCallbackHandle is probably something new.

This is the function responsible for taking your callbackDispatcher and registering it with the Flutter engine.

It can be seen as a simple key-value map inside the Flutter engine.

The key is the hashcode of the callbackDispatcher.

The value is a handle to the entry point itself.

We only send this hashcode to native over a MethodChannel.

Android/iOS will then save it for later use.