Flutter-如何从后台任务播放铃声并让用户停止铃声?

时间:2020-06-27 11:30:48

标签: flutter background

我想在我的flutter应用程序处于后台时播放铃声,并让用户停止它。

我想在用户选择的特定时间间隔(例如3分钟或58分钟)之后播放铃声,然后用户应该能够停止铃声。当flutter应用程序在前景中时有效,而当应用程序在背景中时(例如,当屏幕关闭时)无效。

我当前正在使用Workmanager插件中的callbackDispatcher来进行抖动,这会创建一个新的隔离。我们将其称为 isolate B ,以区别于Flutter启动我的应用时创建的 isolate A

这是callbackDispatcher:

void callbackDispatcher() {
  print('callbackDispatcher');

    FlutterRingtonePlayer.play(
      android: AndroidSounds.ringtone,
      ios: IosSounds.glass,
      looping: false,
      // Android only - API >= 28
      volume: 1,
      // Android only - API >= 28
      asAlarm: true, // Android only - all APIs
    );

    return Future.value(true);
  });
}

问题在于我可以从隔离B开始播放铃声,但是我不知道如何让用户停止它。

到目前为止,我已经尝试过:

  • 单击通知时,从隔离A调用FlutterRingtonePlayer.stop(),但这不会停止在隔离B中播放的铃声。
  • 从隔离B开始通知,然后单击一下即可停止隔离B中的铃声。但是由于某种原因,在隔离B中创建通知时不会弹出该通知。
  • 从隔离A调用FlutterRingtonePlayer.stop(),但这不会停止在隔离B中播放的铃声。
  • 使用一种用于播放和停止铃声的方法来创建全局类,然后在隔离B中使用它来播放铃声,并在隔离A中使用它来停止铃声,但这还是行不通的...

我不知道如何与Workmanager创建的Isolate B通信,并且似乎他们的文档没有指定如何与创建的新Isolate通信...

我还能尝试什么?我唯一的目标是在后台模式下播放铃声,然后让用户停止铃声。

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题(但是,使用android警报管理器软件包而不是workmanager-但是,我相信概念仍然相同)。我可以解决以下问题。

隔离就像线程,但是不共享内存-从这个意义上讲,它们类似于Linux / Unix进程。因此,FlutterRingtonePlayer中的全局变量/静态变量在两个隔离中都不相同-它们是两个不同的实例。因此,我们需要使用消息在隔离群之间进行通信。

我们可以使用ReceivePort和SendPort在两个隔离之间进行通信。我们需要在后台隔离运行的回调中定义一个ReceivePort(dart:isolate包)。我们需要在IsolateNameServer(dart:ui)中注册与该接收端口( .sendPort)对应的发送端口。然后,我们需要在后台隔离中监听该ReceivePort。从前台隔离区(当用户单击您的示例中的通知时),我们可以使用IsolateNameServer.lookup查找该SendPort并将消息发送到后台隔离区。当该消息在后台隔离中处理时,我们可以执行FlutterRingtonePlayer.stop()。

答案 1 :(得分:0)

我也是,我在使用 android 闹钟管理器和音频播放器时遇到了这个问题,但我是这样修复的:

    stopTheSound() async {
    await AndroidAlarmManager.oneShot(Duration(seconds: 0), 4, stopSound,
        exact: true, wakeup: true, alarmClock: true, allowWhileIdle: true);
  }
  
  static stopSound() async {
    if (MyApp.isPlaying) {
      var res = await audioPlugin.stop();
      if (res == 1) {
        MyApp.isPlaying = false;
      }
    }
  }

我使用警报管理器来调用声音,所以我再次使用它来停止它。