每天午夜执行 Flutter 后台任务以处理和安排当天的通知

Mic*_*ton 9 notifications android android-notifications dart flutter

应用:任务提醒。用户创建一个任务并安排该任务到期的时间。

这个包flutter_local_notification允许我在用户创建此任务时安排未来的通知。如果我在任务到期时安排一个通知,那很好。

但是,如果用户忘记完成该任务并且该任务到期的日期已经过去(原始通知已经过去)。我希望应用程序每天一次继续通知用户他们尚未完成此任务,直到他们打开应用程序取消通知/将任务标记为完成。

我敢肯定其他人一定已经创建了这样的东西,但我正在努力在网上找到明确的解决方案,所以我想我会在这里问,看看人们对什么是最佳实践的意见。

我能想到的两种解决方案:


每日后台任务

每天运行一次的后台任务,以检查当天哪些任务到期和逾期,然后安排当天晚些时候的某个时间点的通知。

系列活动

  • 每天 00:00 应用程序运行后台任务,检查今天到期的任务
  • 如果任务今天到期或已过期。安排当天晚些时候的通知。
  • 如果应用程序从未打开过,这个检查和发送通知的过程每天都会重复。

每天重复通知

在“星期一”到期的示例任务

而不是每天运行后台任务。对于这个示例任务,我想我可以在星期一安排通知,同时还无限期地安排每天(星期二,星期三,星期四......)之后的每天重复通知。然后,如果用户打开应用程序并完成任务,这些重复通知将被取消。如果没有,用户每天都会收到通知,直到他们通知为止。

我认为这种方法可行,但我想避免在未来安排这么多通知,而只安排“今天”通知。因为这个应用程序可能有很多由用户创建的任务。


我的 flutter 应用程序目前仅在Android上运行,但我不想排除iOS。所以理想的方法是跨平台工作。

所有数据都存储在本地,因此我无法让后端完成数据检查和发送推送通知。

关于这个问题的解决方案的想法?

moe*_*far 5

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

像往常一样将此插件导入到您的项目后,将以下内容添加到标签内的 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>
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);
}
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 在固定时间、日期或时间间隔定期运行任务。但 corn 的唯一缺点是一旦应用程序终止, 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:信息

测试定时任务:crontab