【问题标题】:Android Alarm Manager is not working for Flutter Project AppAndroid 警报管理器不适用于 Flutter Project App
【发布时间】:2019-07-12 12:52:05
【问题描述】:

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

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

我使用此链接中的代码: 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): 

【问题讨论】:

  • 哪个错误?请添加错误信息
  • 错误更新有问题
  • 让我检查一下...
  • 你有没有正确的配置github.com/flutter/flutter/issues/26526
  • 你使用的是什么版本的android_alarm_manager?>

标签: android dart flutter alarmmanager


【解决方案1】:

在挣扎了几个小时后,我终于自己解决了这个问题(但感觉时间更长了!)。当我实际上克隆了包含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);
  }
}

至于你需要把这个文件放在哪里,他们的例子看起来像这样,但你的可能是&lt;your project dir&gt;/android/app/src/main/java/com/example/&lt;your project name&gt;

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

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

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

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

接下来,在&lt;application&gt;&lt;/application&gt; 标签内,添加:

<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>

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

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

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

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

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

【讨论】:

  • 感谢您的回复。我尝试这个答案,但我收到了我在 Application.java 文件中定义的警报服务的错误。我还分享了错误以及 Application.java 类的代码。
  • 对不起,我不知道如何帮助你。我很幸运能够让它为自己工作,因为我对 Android 开发不太了解!编辑,实际上,看看你的截图,AlarmService 是红色的事实看起来它没有导入它,可能是因为它没有安装。我会先调查一下。
  • 最好将 Application.java 代码包含在答案中,而不是参考它。直到我看到 Sen Sokha 的答案中的实际代码,我才意识到它的重要性。也许还可以将名称更改为 MyApplication 以使链接更清晰,即这是您选择的名称。
  • @Bill99 我已按照您的建议将 Application.java 文件的内容添加到我的答案中。我将保留与他们文档中的名称相同的名称,特别是因为我自己对此知之甚少,无法可靠地重命名我不需要的东西!这里有一些货物崇拜编程,但它有效。
  • 无法解析符号“AlarmService”。无法解析导入语句中的“androidalarmmanager”。做什么?
【解决方案2】:

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

原因:报警回调需要访问其他 Flutter 插件,包括报警管理器插件本身,需要教后台服务如何初始化插件。由于 AlarmManager 使用单独的隔离,因此在调度代码中使用的任何插件都需要为 AlarmManager 单独初始化。

解决方案:在Application.java注册报警管理插件本身如下;(解决官方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"));
  }
}

*注意:如果您在项目中使用了其他插件,您也应该将其全部添加到您的Application.java 文件中。

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...

  }
}

【讨论】:

  • 我遇到了GeneratedPluginRegistrant.registerWith(registry); 的问题,因为我的一些插件需要活动上下文。 AndroidAlarmManagerPlugin.registerWith 解决了我的问题。
  • 当我尝试这个时,我遇到了 sharedpreference 的问题,在颤振代码中我使用 sharedpreference,得到一个错误,没有找到实现
  • @shahanakareen 请再试一次,flutter clean &amp; flutter run
  • 如果您仍然有错误,请提及您在Application.java 中使用的所有频道插件,如下所示; SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));
【解决方案3】:

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

等待AndroidAlarmManager.initialize();

当应用开始运行时会发生什么:

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

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

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

这个函数只是在指定的延迟时间之后安排一个回调。这将失败,因为回调处理程序未注册。这意味着,超时后,它找不到负责运行“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);
      }
}

【讨论】:

  • 感谢您的回答。我更新了我的代码,但仍然报错。
  • 我想这是一个新错误。更新了答案。不要只是盲目地复制一个插件并期望它可以工作,也许尝试理解它。
  • 我以前用过这段代码。正如您所提到的,此代码放在 Application.java 类中,但该文件给出错误并且它没有选择一些 AlarmService。以及如何更改清单文件中的 android:name? -@CheunYee
  • 应用java必须放到Android的build文件夹下,不会编译成Flutter。这个插件有点复杂,因为它需要在后台调用一些东西。清单文件可以在 android/src/main 中找到。
  • 我用屏幕截图更新了我的问题,它在 AlarmService 上给出了一个错误,并说 AlarmService 是未解决的参考-@CheunYee
【解决方案4】:

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

the documentation of the plugin 中的通知声明:

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

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

欲了解更多信息,请参阅Android Developers element documentation

【讨论】:

    【解决方案5】:

    我遇到了同样的问题。只需打开android项目。执行 Gradle 同步。接下来,执行“构建 -> 清理项目”和“构建 -> 重建项目”。

    【讨论】:

      【解决方案6】:

      如果您只为 Android 开发此应用程序,那么您可以创建 native foreground/background service,它会在每个给定的时间间隔内运行。然后使用platform channel,您可以在button点击上从dart调用服务,如果您希望它在特定条件下每次都运行,或者使用shared prefrence从主页中的initState()调用本机服务。您可能知道,一旦启动本机服务,它将在每个给定的时间间隔(如分钟或 24 小时)后调用自己。

      【讨论】:

        猜你喜欢
        • 2018-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-27
        相关资源
        最近更新 更多