Search code examples
androidflutterdartalarmmanagerdart-isolates

How to stop playing a sound initiated in AlarmManager in Flutter


I'm currently writing an alarm clock app in Flutter and need to be able to start playing a custom sound at a specific time, even without the app currently running. I've already been able to achieve this with the following code (Using Android Alarm Manager Plus Flutter Package):

onTap() async {
    await AndroidAlarmManager.oneShot(
                    const Duration(seconds: 5),
                    0,
                    playRingtone,
                    exact: true,
                    wakeup: true,
                  );
}

Future<void> playRingtone() async {
  await FlutterRingtonePlayer.play(
    fromAsset: "assets/song.mp3",
    looping: true, // Android only - API >= 28
    volume: 0.1, // Android only - API >= 28
    asAlarm: true, // Android only - all APIs
  );
}

For test purposes I'm firing an alarm 5 seconds from the point in time where the associated button is pressed. Now, here is where I run into a problem: It turns out to be rather diffcult to stop playing that same sound.

The code that is supposed to stop the sound from playing

FlutterRingtonePlayer.stop();
AndroidAlarmManager.cancel(0);

is not doing much of anything. I run that code from another button tap somewhere else in the app. I suppose things are not working out because FlutterRingtonePlayer starts playing from an isolate/thread inside AlarmManager and so even if I kill the AlarmManager isolate/thread, the FlutterRingtonePlayer isolate (inside AlarmManager isolate) still keeps running. Not sure though..


Solution

  • I just found the answer, which is actually quite simple: One needs to start another oneShot with AlarmManager using the same ID as before and simply stop the ringtone from there:

    await AndroidAlarmManager.oneShot(
                              const Duration(seconds: 0),
                              0, //This ID has to be the same as above
                              stopRingtone,
                              exact: true,
                              wakeup: true,
                            );
    
    Future<void> stopRingtone() async {
      await FlutterRingtonePlayer.stop();
    }