Flutter + AlarmManager = ⏰

原文 https://medium.com/flutter-community/flutter-alarmmanager-f184671240cb

前言

如果您是一名 Android 开发人员,当您希望将应用程序安排在将来的特定时间运行时,可以使用 AlarmManager。如果你是一个 iOS 开发者,这种类型的组件并不存在。

如果你是一个 Flutter 开发者,你会怎么做?

像大多数与 Flutter 相关的事情一样,当您想要使用特定于平台的组件时,您需要公开它的功能。

AlarmManager 也不例外。

本文将介绍 Android AlarmManager Plus 包,并展示如何在应用程序中使用它。

准备好设闹钟了吗?

正文

Setup 设置

  • 打开 pubspec.yaml 文件并添加以下内容:
dependencies:
  android_alarm_manager_plus: ^2.0.6

Something 免责声明 → 撰写本文时,最新版本是 2.0.6

  • 运行 pub get下载依赖项

我们将使用您在 Android Studio 中创建 Flutter 项目时获得的普通项目(减去所有计数器逻辑)。

  • 打开 AndroidManifest.xml 文件并添加以下权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

<!-- For apps with targetSDK=31 (Android 12) -->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
  • 在您的应用程序标签中,添加以下内容:
<service
    android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="false"/>
<receiver
    android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmBroadcastReceiver"
    android:exported="false"/>
<receiver
    android:name="dev.fluttercommunity.plus.androidalarmmanager.RebootBroadcastReceiver"
    android:enabled="false"
    android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

最后,你的 AndroidManifest 文件应该是这样的:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tomerpacific.alarm_manager_example">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <!-- For apps with targetSDK=31 (Android 12) -->
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>

   <application
        android:label="alarm_manager_example"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
       <service
           android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmService"
           android:permission="android.permission.BIND_JOB_SERVICE"
           android:exported="false"/>
       <receiver
           android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmBroadcastReceiver"
           android:exported="false"/>
       <receiver
           android:name="dev.fluttercommunity.plus.androidalarmmanager.RebootBroadcastReceiver"
           android:enabled="false"
           android:exported="false">
           <intent-filter>
               <action android:name="android.intent.action.BOOT_COMPLETED" />
           </intent-filter>
       </receiver>
    </application>
</manifest>

AndroidManifest.xml

Alarm Bells Are Ringing

该包公开了一个 AndroidAlarmManager 对象,该对象具有以下(相关)方法:

  • oneShot : 一次性触发警报
  • oneShotAt : 在特定日期触发一次性警报
  • periodic : 在规定的时间间隔内触发警报

让我们详细讨论每个选项。

OneShot 方法接受以下参数:

 static Future<bool> oneShot(
    Duration delay,
    int id,
    Function callback, {
    bool alarmClock = false,
    bool allowWhileIdle = false,
    bool exact = false,
    bool wakeup = false,
    bool rescheduleOnReboot = false,
  })

oneShot method

前三个参数(延迟、 id 和 callback)是不言自明的,因此我们将关注其余的。

  • AlarmClock - 一个标志,指示计时器是否将与 Android 的 AlarmManagerCompact.setAlarmClock 一起设置
  • AllowWhileIdle - 一个标志,指示计时器是否将用 AlarmManagerCompat.setExactAndAllowWhildle 或 AlarmManagerCompat.setAndAllowWhileIdle 设置
  • Sec - 指示是否使用 AlarmManagerCompat.setExact 设置计时器的标志
  • wakeup - 一个标志,表明如果设备将被唤醒时,警报将被触发
  • rescheduleOnReboot - 一个标志,表明如果警报将持续之间的设备重新启动

OneShotAt 方法与 oneShot 方法非常相似,只有一个关键字不同。第一个参数是一个 DateTime 对象,该对象设置警报触发的时间,而不是持续时间类型的延迟。

static Future<bool> oneShotAt(
    DateTime time,
    int id,
    Function callback, {
    bool alarmClock = false,
    bool allowWhileIdle = false,
    bool exact = false,
    bool wakeup = false,
    bool rescheduleOnReboot = false,
  })

periodic 方法接受下参数:

static Future<bool> periodic(
    Duration duration,
    int id,
    Function callback, {
    DateTime? startAt,
    bool allowWhileIdle = false,
    bool exact = false,
    bool wakeup = false,
    bool rescheduleOnReboot = false,
  })

正如您所看到的,这个方法在它接受的参数中也是类似的。这里最重要的论点是:

  • StartAt : 指示第一次触发警报的时间
  • duration : 负责每隔一段时间重新触发警报。

记得设置闹钟

关于 Alarm Manager Plus 包需要注意的一点是,它使用隔离程序来运行警报。隔离类似于线程,只是它们不共享内存。因此,它们与信息交流。

因此,您必须将警报处理程序(callback)声明为静态的,以便可以访问它们。

你可以在这里了解更多关于 isolates 的信息。

代码

https://github.com/ducafecat/MediumArticles

结束语

如果本文对你有帮助,请转发让更多的朋友阅读。

也许这个操作只要你 3 秒钟,对我来说是一个激励,感谢。

祝你有一个美好的一天~

猫哥课程


© 猫哥

  • 微信 ducafecat

  • https://wiki.ducafecat.tech

  • https://ducafecat.com

Last Updated:
Contributors: ducafecat