Android Alarm Manager 不适用于 Flutter Project App

Android Alarm Manager is not working for Flutter Project App

我已经在我的新 Flutter 应用程序中安装了 Android Alarm Manager 插件。我尝试使用插件的示例代码,但它在控制台中给出了错误。

请建议如何使 Android 警报管理器插件工作。 如何将 Dart 的 android_alarm_manager 集成到应用程序中,以便用户在他们在日程中选择的时间到达时收到警报?

我使用这个 link 中的代码: https://github.com/flutter/plugins/tree/master/packages/android_alarm_manager

main.dart:

import 'dart:isolate';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';
    
void printHello() {
  final DateTime now = DateTime.now();
  final int isolateId = Isolate.current.hashCode;
  print("[$now] Hello, world! isolate=${isolateId} function='$printHello'");
}

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

class Application extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(),
    );
  }
}

Application.java:

package io.flutter.plugins.androidalarmmanagerexample;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
    
public class Application extends FlutterApplication implements PluginRegistrantCallback {
    @Override
    public void onCreate() {
        super.onCreate();
    
        AlarmService.setPluginRegistrant(this);
    }

    @Override
    public void registerWith(PluginRegistry registry) {
        GeneratedPluginRegistrant.registerWith(registry);
    }
}               

当我 运行 此代码时,它向控制台打印以下错误:

E/flutter ( 6831): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(error, Attempt to invoke interface method 'void io.flutter.plugin.common.PluginRegistry$PluginRegistrantCallback.registerWith(io.flutter.plugin.common.PluginRegistry)' on a null object reference, null)
E/flutter ( 6831): #0      JSONMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:149:7)
E/flutter ( 6831): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:33)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #2      AndroidAlarmManager.initialize (package:android_alarm_manager/android_alarm_manager.dart:76:10)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #3      main (package:alarmdemo/main.dart:12:29)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #4      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter ( 6831): #5      _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6831): #6      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6831): #7      _runZoned (dart:async/zone.dart:1516:10)
E/flutter ( 6831): #8      runZoned (dart:async/zone.dart:1500:12)
E/flutter ( 6831): #9      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter ( 6831): #10     _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
E/flutter ( 6831): #11     _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
E/flutter ( 6831): 
E/flutter ( 6831): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: MissingPluginException(No implementation found for method AlarmService.initialized on channel plugins.flutter.io/android_alarm_manager_background)
E/flutter ( 6831): #0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:300:7)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #1      _alarmManagerCallbackDispatcher (package:android_alarm_manager/android_alarm_manager.dart:49:12)
E/flutter ( 6831): #2      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter ( 6831): #3      _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6831): #4      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6831): #5      _runZoned (dart:async/zone.dart:1516:10)
E/flutter ( 6831): #6      runZoned (dart:async/zone.dart:1500:12)
E/flutter ( 6831): #7      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter ( 6831): #8      _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
E/flutter ( 6831): #9      _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
E/flutter ( 6831): 

这是我更新后的代码:

main.dart:

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

void main() async {
  runApp(MaterialApp(home: Application()));
}
    
class Application extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Center(
          child: RaisedButton(
            child: Text('Hello'),
            onPressed: () {
              runAlarm();
            },
          ),
        ),
      ),
    );
  }

  void runAlarm() {
    AndroidAlarmManager.oneShot(
      Duration(seconds: 10),
      0,
      printHello,
      wakeup: true,
    ).then((val) => print(val));
  }

  static void alarmTest() {
    print("test");
  }
}

它不会向控制台打印任何错误,但会打印以下两行:

E/AlarmService(11943): Fatal: failed to find callback
I/AlarmService(11943): AlarmService has not yet started.

我也尝试初始化警报管理器,但它向控制台打印错误:

void runAlarm() {
  AndroidAlarmManager.periodic(
    Duration(seconds: 10),
    0,
    printHello,
    wakeup: true,
  ).then((val) => print(val)).catchError((e) {
    print(e);
  });
}

错误:

E/flutter ( 6831): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(error, Attempt to invoke interface method 'void io.flutter.plugin.common.PluginRegistry$PluginRegistrantCallback.registerWith(io.flutter.plugin.common.PluginRegistry)' on a null object reference, null)
E/flutter ( 6831): #0      JSONMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:149:7)
E/flutter ( 6831): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:33)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #2      AndroidAlarmManager.initialize (package:android_alarm_manager/android_alarm_manager.dart:76:10)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #3      main (package:alarmdemo/main.dart:12:29)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #4      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter ( 6831): #5      _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6831): #6      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6831): #7      _runZoned (dart:async/zone.dart:1516:10)
E/flutter ( 6831): #8      runZoned (dart:async/zone.dart:1500:12)
E/flutter ( 6831): #9      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter ( 6831): #10     _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
E/flutter ( 6831): #11     _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
E/flutter ( 6831): 
E/flutter ( 6831): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: MissingPluginException(No implementation found for method AlarmService.initialized on channel plugins.flutter.io/android_alarm_manager_background)
E/flutter ( 6831): #0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:300:7)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #1      _alarmManagerCallbackDispatcher (package:android_alarm_manager/android_alarm_manager.dart:49:12)
E/flutter ( 6831): #2      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter ( 6831): #3      _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6831): #4      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6831): #5      _runZoned (dart:async/zone.dart:1516:10)
E/flutter ( 6831): #6      runZoned (dart:async/zone.dart:1500:12)
E/flutter ( 6831): #7      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter ( 6831): #8      _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
E/flutter ( 6831): #9      _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
E/flutter ( 6831): 

您没有初始化警报对象和回调处理程序。

await AndroidAlarmManager.initialize();

当应用程序启动时会发生什么运行宁此:

 void main() async {
    runApp(MaterialApp(home: Application()));
 }

应用程序只是 运行 并为您绘制 UI。单击按钮后,将调用以下方法:

AndroidAlarmManager.oneShot(
   Duration(seconds: 10),
   0,
   printHello,
   wakeup: true,
)

此函数只是在指定的延迟时间后安排回调。这将失败,因为回调处理程序未注册。意思是,超时后,它找不到 'anyone' 负责 运行 和 'printHello'。

编辑:

您还需要覆盖一个方法来帮助插件在创建时自行注册。

像下面这样创建一个新文件:

yourapprootfolder/android/app/src/main/java/io/flutter/plugins/androidalarmmanagerexample/Application.java

在 .java 文件中,放入:

package io.flutter.plugins.androidalarmmanagerexample;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;

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

  @Override
  public void registerWith(PluginRegistry registry) {
    GeneratedPluginRegistrant.registerWith(registry);
  }
}

或在 Kt 文件中:

package io.flutter.plugins.androidalarmmanagerexample;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;

class Application : FlutterApplication(), PluginRegistrantCallback {
      override fun onCreate() {
        super.onCreate();
        AlarmService.setPluginRegistrant(this);
      }

      override fun registerWith(registry: PluginRegistry) {
        GeneratedPluginRegistrant.registerWith(registry);
      }
}

如果您只为 android 开发此应用程序,那么您可以为每个给定的时间间隔创建 native foreground/background service,其中 运行s。然后使用 platform channel 你可以在 button 上调用来自 dart 的服务,如果你想要它 运行 每次在特定条件下或使用 shared prefrenceinitState() 在你的主页。正如您可能知道的那样,一旦本机服务启动,它将在每个给定的时间间隔( 分钟或 24 小时 )后调用自身。

你是在 AndroidManifest.xml 中引用你 Application 吗?顺便说一句(我会使用不同的名称,以免与 Android 的 Application 混淆,例如 MyFlutterApplication)。

the documentation of the plugin 中的通知指出:

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

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

有关详细信息,请参阅 Android Developers element documentation

我遇到了同样的问题。只需打开 android 项目。执行 Gradle 同步。接下来,执行 "build -> clean project" 和 "build -> rebuild project".

问题:未处理的异常:MissingPluginException(未在通道 plugins.flutter.io/android_alarm_manager_background 上找到方法 AlarmService.initialized 的实现)

原因:Alarm回调会需要访问其他Flutter插件,包括alarmmanager插件本身,需要教会后台服务如何初始化插件。由于 AlarmManager 使用单独的 isolate,任何在调度代码中使用的插件都需要单独为 AlarmManager 初始化。

解决方案:在Application.java中注册alarm manager插件本身如下;(已解决官方flutter repo问题#21969

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;
import io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin;

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

  @Override
  public void registerWith(PluginRegistry registry) {
    // GeneratedPluginRegistrant.registerWith(registry);
    AndroidAlarmManagerPlugin.registerWith(registry.registrarFor("io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin"));
  }
}

*Note: if you have used another plugins in your project, You would have also add it all into your Application.java file.

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

  }

  @Override
  public void registerWith(PluginRegistry registry) {
    // GeneratedPluginRegistrant.registerWith(registry);

    //add AndroidAlarmManagerPlugin plugin register  if you work with arlarm
    AndroidAlarmManagerPlugin.registerWith(registry.registrarFor("io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin"));

    //add PathProviderPlugin plugin register  if you work with Access Path Device
    PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));

    //add SqflitePlugin plugin register  if you work with sqflite
    SqflitePlugin.registerWith(registry.registrarFor("com.tekartik.sqflite.SqflitePlugin"));

    //add PermissionHandlerPlugin plugin register  if you work with permission handler
    PermissionHandlerPlugin.registerWith(registry.registrarFor("com.baseflow.permissionhandler.PermissionHandlerPlugin"));

    //add SharedPreferencesPlugin plugin register  if you work with share preferences
    SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));

    // something else...

  }
}

经过几个小时的努力(但感觉时间长了很多!),我终于自己解决了这个问题。当我实际克隆包含 android_alarm_managerFlutter Plugins Github repository 并查看示例代码并查看它在 IDE 中的布局时,突破出现了,而不是在线查看孤立的文件。

如果您不精通 Android Java 开发,自述文件并不清楚具体要做什么,但是当您查看工作示例代码时就会清楚。

您需要将示例目录中提供的 Application.java 文件放入您的实际项目中,与现有 MainActivity.java 文件位于同一文件夹中。内容应如下所示:

package io.flutter.plugins.androidalarmmanagerexample;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;

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

  @Override
  public void registerWith(PluginRegistry registry) {
    GeneratedPluginRegistrant.registerWith(registry);
  }
}

至于你需要把这个文件放在哪里,他们的例子是这样的,但你的可能是这样的 <your project dir>/android/app/src/main/java/com/example/<your project name>:

完成此操作后,您必须Application.java第一行的包名称从package io.flutter.plugins.androidalarmmanagerexample;更新为匹配您的项目使用的任何包(请参阅您现有 MainActivity.java 的第一行)。如果您不这样做,gradle 将找不到它并且没有任何效果!

您现在可以按照 Readme 中的建议,添加权限等:

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

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

Next, within the <application></application> 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>

最后一部分是我最困惑的部分。听起来他们很含糊,但如果你之前做的一切都完全正确,那实际上正是你需要做的。

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

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

只需将您的 android:name 更改为 .Application,这意味着它现在将利用我们之前添加的 Application.java

就是这样!希望您现在可以 运行 您的应用程序。