I am using Android AlarmManger
to set a oneShotAt
alarm at a particular date and time. I am playing a looping sound with the help of FlutterRingtonePlayer
as soon as the alarm is activated.
class _MyHomePageState extends State<MyHomePage> {
TimeOfDay _time = TimeOfDay.now();
DateTime _date = DateTime.now();
final int helloAlarmID = 0;
static playLocalAsset() {
final DateTime now = DateTime.now();
final int isolateId = Isolate.current.hashCode;
print("[$now] Hello, world! isolate=${isolateId}");
FlutterRingtonePlayer.playAlarm(looping: true);
}
static stopLocalAsset() {
print("TEST");
FlutterRingtonePlayer.stop();
}
void stopMusic() async {
AndroidAlarmManager.oneShot(Duration(seconds: 0), helloAlarmID, stopLocalAsset);
}
//Date and Time Picking
Future<Null> selectTime(BuildContext context) async {
await selectDate(context);
_time = await showTimePicker(context: context, initialTime: _time);
_date = DateTime(_date.year, _date.month, _date.day, _time.hour, _time.minute);
print(_date);
await AndroidAlarmManager.oneShotAt(_date, helloAlarmID, playLocalAsset); //ALARM SET HERE
}
Future<Null> selectDate(BuildContext context) async {
_date = await showDatePicker(context: context, initialDate: _date, firstDate: _date, lastDate: DateTime(2222));
}
So alarm is set perfectly and it rings on exact time set. However, when I want to stop the music, I am unable to stop it. So I had to use another oneShot
of AlarmManager
in order to access the isolate and stop the music as seen in the code above. This stops the music, but it takes more than 3 seconds just to stop the music.
My question is, how do I make the AlarmManger
stop the music IMMEDIATELY as soon as the stop button is pressed.
Thank You, Jack
EDIT: Removed a line that was kept for testing.
So after searching through the web I finnally found a way to stop the player immediately after you press.
As AlarmManger
creates an isolate, you must create a recieve port inside callback
function of the AlarmManger
.In my case it is static playLocalAsset()
static playLocalAsset() {
ReceivePort rcPort = new ReceivePort();
IsolateNameServer.registerPortWithName(rcPort.sendPort, portName);
rcPort.listen((v) {
FlutterRingtonePlayer.stop();
});
final DateTime now = DateTime.now();
final int isolateId = Isolate.current.hashCode;
print("[$now] Hello, world! isolate=${isolateId}");
FlutterRingtonePlayer.playAlarm(looping: true);
}
create a portname outside all functions (a global variable per say) like
const String portName = "ConnectingIsolate";
Now in your stop button function create a SendPort
which will send to the portname that you have declared globally. In my case, the final stopLocalAsset()
will look like
void stopMusic() {
SendPort sendPort = IsolateNameServer.lookupPortByName(portName);
sendPort.send("Abcd");
}
So, basically, when you send something through SendPort
, the receiever port (which is in isolate) will listen and perform whatever operation that you have provided in rcport.listen
function, which in my case is to stop the player.
Hope this helps.