I am having trouble to stop the alarm from ringing even after I have pressed the stopAlarm button. I cannot figure out how to get access to the same Ringtone instance and call stop().
This is my start alarm switch in MainActivity java class.
public void switchClicked(View view) {
if (((Switch) view).isChecked()) {
Log.d("MainActivity", "Alarm On");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, alarmTimePicker.getHour());
calendar.set(Calendar.MINUTE, alarmTimePicker.getMinute());
Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
setAlarmText("ON");
} else {
alarmManager.cancel(pendingIntent);
setAlarmText("OFF");
Log.d("MainActivity", "Alarm Off");
}
}
public void setAlarmText(String alarmText) {
alarmTextView.setText(alarmText);
}
Here is my StopAlarm button in MainActivity java class.
public void stopAlarm(View view) {
setAlarmText("Alarm stopped");
Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(pendingIntent);
}
This is the AlarmReciver java class.
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
MainActivity inst = MainActivity.instance();
inst.setAlarmText("Alarm! Wake up! Wake up!");
Uri alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
if (alarmUri == null) {
alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
}
Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
ringtone.play();
}
}
steps:
add
RingtonePlayingService
to your project (don't forget to declare it in manifest)remove code you have inside
onReceive
and put this:now
RingtonePlayingService
is handling ringtone playing and keeps reference to it. YourstopAlarm
method is just cancelling potentially pending alarm, so if it didn't fired yet until stop button click it won't never fire. But when it started ringing already then you should stopringtone
instance held by started service. Add on the end of your method:Now
stopAlarm
do both: cancels pending alarm (if any) and stops service (if is alive), which is potentially playing ringtonealso remove
MainActivity.instance()
pattern, it is bad as hell... When you set future alarm (e.g. now+1h) and system (or user) remove app from memory before it gets fired then you will getNullPointerException
, as.instance()
isnull
, and you are immediatelly trying to accessinst.setAlarmText
method. Intead of you may use Local Broadcasting or service binding to update your UI - send broadcasts/messages to yourActivity
from workingRingtonePlayingService
with start/stop/current status