如何在Flutter中安排后台任务?

Gur*_*thi 17 dart flutter flutter-dependencies

我一直在寻找这个,但没有找到任何包或在Flutter中安排后台任务的方法.就像在Android中一样WorkManager,AlarmManager.

我知道我可以使用这些类来访问这些类MethodChannel,但我想要一些适用于iOS和Android的东西.

(非常令人失望的是,移动框架无法安排后台任务).

tim*_*tim 20

有一篇Medium 博客文章解释了如何做到这一点。
但是,我们认为设置起来太复杂了,所以碰巧我们创建了一个插件来帮助您解决这个问题。

//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
)
Run Code Online (Sandbox Code Playgroud)

我们支持 Android 的 Workmanager 和 iOS performFetch


目前它只适用于 Android 项目,但我们很快就会关注 iOS。
我会在可用时更新此答案。


我们现在也有 iOS 支持。它仍然是早期的 alpha,但试一试。
我们也写了一篇免费的Medium帖子。

  • 有适用于 Android 的解决方案,但我正在寻找同时适用于 iOS 和 Android 的解决方案。我已经和很多正在寻找这个问题解决方案的开发人员交谈过。 (2认同)
  • 我们可以使用Workmanager插件以1秒的频率注册PeriodicTask吗?根据文档,“最小频率为 15 分钟” (2认同)
  • android_alarm_manager 和 workmanager。在这些之间,即使应用程序从内存中滑动/关闭,哪些也能够运行任务? (2认同)

fel*_*eon 5

您要做的事情(即跨平台调度)不是Flutter的限制。这是iOS的限制。请参阅此GitHub注释中引用的SO帖子


sil*_*orp 5

解决方案 1: android_alarm_manager_plus是安排后台任务的最佳解决方案。但唯一的缺点是只支持Android。

注意: 如果您使用的是android_alarm_manager版本,请迁移到 Plus 版本 :D

开始吧:

像往常一样将此插件导入您的项目后,将以下内容添加到您的 AndroidManifest.xml 标签内:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
Run Code Online (Sandbox Code Playgroud)

接下来,在标签内,添加:

<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>
Run Code Online (Sandbox Code Playgroud)

然后在 Dart 代码中添加:

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);
}
Run Code Online (Sandbox Code Playgroud)

如果您想每天在特定时间安排任何任务,您需要执行以下操作:

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
   );
}
Run Code Online (Sandbox Code Playgroud)

如果警报回调需要访问其他 Flutter 插件,包括警报管理器插件本身,则可能需要通知后台服务如何根据应用程序使用的 Flutter Android 嵌入来初始化插件。

这是通过给 AlarmService 一个回调来调用应用程序的 onCreate 方法来完成的。

具体来说,它的Application类如下:

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"));
    }
}
Run Code Online (Sandbox Code Playgroud)

这必须反映在应用程序的 AndroidManifest.xml 中。例如:

<application
        android:name=".Application"
        ...
Run Code Online (Sandbox Code Playgroud)

解决方案 2: Cron是另一个安排后台任务的最佳解决方案。Cron 在固定的时间、日期或间隔定期运行任务。但是玉米的唯一缺点是一旦应用程序被杀死,cron 就无法按预期在后台工作。

一个简单的使用示例:

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');
  });
}
Run Code Online (Sandbox Code Playgroud)

一般如何设置 cronjob:信息

测试 cronjob:crontab