How to schedule background tasks in Flutter?

There is a Medium blogpost that explains how to do this.
However we thought it was way too complicated to set up so it just happens we created a plugin that aids you with this.

//Provide a top level function or static function.
//This function will be called by Android and will return the value you provided when you registered the task.
//See below
void callbackDispatcher() {
  Workmanager.executeTask((task) {
    print("Native echoed: $task");
    return Future.value(true);
  });
}

Workmanager.initialize(
    callbackDispatcher, //the top level function.
    isInDebugMode: true //If enabled it will post a notification whenever the job is running. Handy for debugging jobs
)

We support Android's Workmanager and iOS performFetch


For now it only works for Android project, but we are looking at iOS soon.
I'll update this answer when it is available.


We have iOS support now too. It is still early alpha, but give a go.
We wrote a complimentary Medium post too.


SOLUTION 1: android_alarm_manager_plus is the best solution to schedule background tasks. But the only disadvantage is only support Android.

Note: if you are using android_alarm_manager version, please migrate to the Plus version :D

Let's start:

After importing this plugin to your project as usual, add the following to your AndroidManifest.xml within the tags:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

Next, within the tags, add:

<service
    android:name="io.flutter.plugins.androidalarmmanager.AlarmService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="false"/>
<receiver
    android:name="io.flutter.plugins.androidalarmmanager.AlarmBroadcastReceiver"
    android:exported="false"/>
<receiver
    android:name="io.flutter.plugins.androidalarmmanager.RebootBroadcastReceiver"
    android:enabled="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"></action>
    </intent-filter>
</receiver>

Then in Dart code add:

import 'package:android_alarm_manager/android_alarm_manager.dart';

void printHello() {
  final DateTime now = DateTime.now();
  final int isolateId = Isolate.current.hashCode;
  print("[$now] Hello, world! isolate=${isolateId} function='$printHello'");
}

main() async {
  final int helloAlarmID = 0;
  await AndroidAlarmManager.initialize();
  runApp(...);
  await AndroidAlarmManager.periodic(const Duration(minutes: 1), helloAlarmID, printHello);
}

If you want to schedule any task every day at a specific time, you need to do something like this:

if (Platform.isAndroid) {
   await AndroidAlarmManager.periodic(
      const Duration(hours: 24), //Do the same every 24 hours
      helloAlarmID, //Different ID for each alarm
      printHello,
      wakeup: true, //the device will be woken up when the alarm fires
      startAt: DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 5, 0), //Start whit the specific time 5:00 am
      rescheduleOnReboot: true, //Work after reboot
   );
}

If alarm callbacks will need access to other Flutter plugins, including the alarm manager plugin itself, it may be necessary to inform the background service how to initialize plugins depending on which Flutter Android embedding the application is using.

This is done by giving the AlarmService a callback to call the application's onCreate method.

In particular, its Application class is as follows:

public class Application extends FlutterApplication implements PluginRegistrantCallback {
    @Override
    public void onCreate() {
        super.onCreate();
        AlarmService.setPluginRegistrant(this);
    }

    @Override
    public void registerWith(PluginRegistry registry) {
        //add AndroidAlarmManagerPlugin plugin register  if you work with arlarm
        AndroidAlarmManagerPlugin.registerWith(registry.registrarFor("io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin"));
    }
}

Which must be reflected in the application's AndroidManifest.xml. E.g.:

<application
        android:name=".Application"
        ...

SOLUTION 2: Cron is another best solution to schedule background tasks. Cron run tasks periodically at fixed times, dates or intervals. But the onliy disadvantage of corn is once the app kill, cron not working in background as expected.

A simple usage example:

import 'package:cron/cron.dart';

main() {
  var cron = new Cron();
  cron.schedule(new Schedule.parse('*/3 * * * *'), () async {
    print('every three minutes');
  });
  cron.schedule(new Schedule.parse('8-11 * * * *'), () async {
    print('between every 8 and 11 minutes');
  });
}

How to setup a cronjob in general: information

Test cronjob: crontab


Use WorkManager lib

dependencies:
  workmanager: ^0.2.3

WorkManager comes under two parts, which run the task in the background.

1. Delayed background work

registerOneOffTask runs the task only once with an initial delay of 10 seconds. This is useful when we need to perform any background work only once.

Example:

Workmanager.registerOneOffTask(
  "1",
  "registerOneOffTask",
  initialDelay: Duration(seconds: 10),
);

2. Periodic background work

This task runs periodically, Since we have not provided a frequency it will be the default 15 minutes. Example:

Workmanager.registerPeriodicTask(
  "2",
  "registerPeriodicTask",
  initialDelay: Duration(seconds: 10),
);

For a detailed explanation follow a blog:

https://medium.com/flutterworld/flutter-perform-background-job-9bce92f0a21e