运行 特定时间 Flutter 应用程序中的任务

Running a task in a Flutter app at certain times

您好flutter/mobile开发人员,

我手头有一个特殊问题,需要一些建议。我需要创建一个应用程序来在一天中的特定时间执行特定任务。时间每天都会更改,它将在午夜(或非高峰时段)通过 REST 调用获取更新时间。无论如何,即使在设备重启等之后,任务也必须在预定的时间完成。我已经对此进行了广泛的研究,并且感觉 Flutter 不能很好地处理预定的任务,尤其是在 iOS它可以出于任何原因终止应用程序。

我研究过的选项是:

  1. workmanager (https://pub.dev/packages/workmanager/changelog): 这似乎是最有希望的,如果不是15分钟的最低频率,这对我来说是不够的。如果到了执行任务的时间,我需要每分钟检查一次。有办法绕过这个限制吗?

  2. 原生解决方案。我对原生 iOS 和 Android 编码几乎没有经验,所以我不喜欢这个解决方案。但是通过一些研究,我看到了一些可以通过这种方法安排任务的例子。

  3. 服务器端通知。从表面上看,这似乎是一个很好的解决方案,我需要这方面的建议。计算是否到 运行 任务的时间将在服务器端发生,并且可以向设备发送通知(例如通过 Firebase),这将触发任务 运行。这是否可行,设备在收到通知时实际上会 运行 编码吗?

所以这些是我的选择。你认为哪个最可行?如果移动经验比我多的人可以帮助我,我将不胜感激,也许有比我提出的三个更好的解决方案。谢谢。

您可以通过 Firebase 发送数据通知,并使用 onBackgroundMessage 回调处理它们。看这里:https://firebase.flutter.dev/docs/messaging/usage#background-messages

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  await Firebase.initializeApp();

  print("Handling a background message: ${message.messageId}");
}

void main() {
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  runApp(MyApp());
}

来自文档 (Android/Apple):

  1. It must not be an anonymous function.
  2. It must be a top-level function (e.g. not a class method which requires initialization).

The times will change daily, and it will get the updated times via a REST call at midnight (or at off peak hours).

这闻起来像糟糕的建筑。为什么?

  • 您在午夜对您的更新服务器进行 DDOS(如果您在同一时区有许多用户)。您可以将您的 HTTP 请求错开几秒钟来解决这个问题,但这是一个创可贴,而不是一个长期的解决方案。
  • 因为您正在反转依赖关系:听起来计时是服务器的责任(因此您的客户调用它来询问最新时间)。您的客户不应该是那些向服务器请求更新的人,因为现在您的客户有 2 个工作:安排计划更新并为用户安排计划任务。让客户端询问服务器是错误的方向。您应该从服务器发送消息以更新设备上的日程安排。
  • 即使您确实轮询服务器以获取日程更新,您也应该在您需要的时间让移动应用程序日程通知/警报。使用静默通知是 iOS 后台调度限制的已知解决方法。在 Android 上,WorkManager 是 not the right library,您应该使用 AlarmManager.
  • 这是另一个 Whosebug 想到使用本地通知来解决问题的方法: used flutter_local_notifications

回答要点

  1. 在 Android 上,不要使用 WorkManager,而是使用 AlarmManager,或者更好的是,安排通知。话虽如此,Android 上有一些特定于制造商的怪癖,请参阅 flutter_local_notifications 文档:

Consequently, scheduled notifications may not work when the application is in the background on certain devices (e.g. by Xiaomi, Huawei). If you experience problems like this then this would be the reason why. As it's a restriction imposed by the OS, this is not something that can be resolved by the plugin.

  1. 不必使用本机代码,通知是标准功能。
  2. 您现在可以保留轮询架构,因为它更简单(但更脏)。即使您愿意使用服务器端架构,我也会将消息从服​​务器发送到客户端以仅更新​​客户端计划,不会触发工作/用户警报,否则当它听起来不像需要互联网时(与社交媒体通知不同),您正在使您的应用程序依赖于互联网。这会导致连接不当的设备出现糟糕的用户体验。