I want to implement a schedule function in my android project. So I Googled for an Alarm manager program but I can`t Resolve Problem.
I want set alarm with custom time that users Determine. I wrote 2 class for service and BroadcastReciver. But alarm is inccorect for example i set 2 min for alarm.but app Arbitrary is work .eg 2 min or 3 or 5 or 1min....
mainActivity:
SharedPreferences preferences1 = getSharedPreferences("min", 0);
String min1 = preferences1.getString("minute", "");
if (min1.length() <= 0) {
s = 120000;
} else {
s = Long.parseLong(min1);
s = s * 60000;
}
t = new Timer();
// Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Called each time when 1000 milliseconds (1 second)
// (the period parameter)
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(CategoryListActivity.this,
Service_class.class);
PendingIntent pintent = PendingIntent.getService(
CategoryListActivity.this, 0, intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), s, pintent);
Log.e("Timer", t.toString());
}
},
// Set how long before to start calling the TimerTask (in
// milliseconds)
0,
// Set the amount of time between each execution (in
// milliseconds)
s);
service_class.java :
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
dbflash = new DatabaseFlashCard(getApplicationContext());
db = dbflash.getReadableDatabase();
SharedPreferences preferences_notify = getSharedPreferences("notify", 0);
Calendar c = Calendar.getInstance();
String time_one = preferences_notify.getString("time_first", "");
String time_two = preferences_notify.getString("time_second", "");
int hour = c.get(Calendar.HOUR_OF_DAY);
if (time_one.length() <= 0) {
time_one = "21";
}
if (time_two.length() <= 0) {
time_two = "5";
}
int timeFirst = Integer.parseInt(time_one);
int timeSecond = Integer.parseInt(time_two);
if (hour < timeFirst && hour > timeSecond) {
// nothing
} else {
// notify and alert
preferences_language = getSharedPreferences("language_sql", 0);
editor_language = preferences_language.edit();
String language = preferences_language.getString("language", "");
String sql="SELECT * FROM " + dbflash.TABLE
+ " where hide='0' ORDER BY RANDOM() LIMIT 1";
if(language.length()>0)
{
if(language.equalsIgnoreCase("0"))
{
sql="SELECT * FROM " + dbflash.TABLE
+ " where hide='0' ORDER BY RANDOM() LIMIT 1";
}
else
{
sql="SELECT * FROM " + dbflash.TABLE
+ " where ids="+language+" and hide='0' ORDER BY RANDOM() LIMIT 1";
}
Cursor cursors = db.rawQuery(sql, null);
for (int i = 0; i < cursors.getCount(); i++) {
cursors.moveToNext();
ID = cursors.getString(cursors.getColumnIndex("ID"));
farsi = cursors.getString(cursors.getColumnIndex("farsi"));
english = cursors.getString(cursors.getColumnIndex("english"));
question = cursors
.getString(cursors.getColumnIndex("question"));
count = cursors.getString(cursors.getColumnIndex("count"));
}
preferences_status = getSharedPreferences("notify_status", 0);
String status = preferences_status.getString("status", "");
SharedPreferences.Editor editor_status;
editor_status = preferences_status.edit();
if (status.length() <= 0) {
status="1";
editor_status.putString("status", "1");
editor_status.commit();
Log.e("Notification Status ", "Enable Now..for First");
} else if(status.equalsIgnoreCase("0")) {
Log.e("Notification Status ", "disable");
}
else
{
Log.e("Notification Status ", "enable");
if (english==null || english=="") {
} else {
SharedPreferences preferences = getSharedPreferences("music", 0);
String address=preferences.getString("address", "");
if(address.length()<=0)
{
mp = MediaPlayer.create(getApplicationContext(), R.raw.ring);
mp.start();
}
else
{
mp = MediaPlayer.create(getApplicationContext(),Uri.parse(address));
mp.start();
}
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent contentIntent = new Intent(this,
QuestionActivity.class);
contentIntent.putExtra("ID", ID);
contentIntent.putExtra("english", english);
contentIntent.putExtra("farsi", farsi);
contentIntent.putExtra("count", count);
contentIntent.putExtra("question", question);
Notification notification = new Notification(
R.drawable.icon, "یاد آوری",
System.currentTimeMillis());
notification.setLatestEventInfo(this, english, "",
PendingIntent.getActivity(this.getBaseContext(), 0,
contentIntent,
PendingIntent.FLAG_CANCEL_CURRENT));
notification.flags = Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(SIMPLE_NOTFICATION_ID,
notification);
}
}
}
}
return START_STICKY;
}
and Myreceiver
public class Myreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent serviceLauncher = new Intent(context, Service_class.class);
context.startService(serviceLauncher);
}
Android Manifest :
<service android:name=".Service_class" />
<receiver
android:name="com.pttat.flashcard.services.Myreceiver"
android:process=":remote" />
how to change my code for Resolve my Problem?
Do I need to change calling alarm manager in Oncreate?
thanks
Related
This periodic job stops executing after exiting the app. Works perfectly fine if the app is still running. I'm using the UsageStatsManager to gather information every 15 minutes. I tried just sending a notification every 15 minutes and it didn't work.
Here's the Scheduler code:
public class JobServiceDashboard extends android.app.job.JobService {
private static final String TAG = "JobServiceDashboard";
private static final int NOTIFICATION_ID = 141;
private boolean jobCancelled = false;
private int totalTime = 0;
private int timeLimit;
private NotificationCompat.Builder builder;
.
.
.
#Override
public boolean onStartJob(final JobParameters jobParameters) {
Log.d(TAG, "Job Started");
timeLimit = jobParameters.getExtras().getInt("limit");
Log.d(TAG, "time limit " + timeLimit);
new Thread(new Runnable() {
#Override
public void run() {
totalTime = 0;
if (jobCancelled) {
jobFinished(jobParameters, false);
}
Calendar cal = Calendar.getInstance();
cal.setTime(Calendar.getInstance().getTime());
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long startTime = cal.getTimeInMillis();
long endTime = System.currentTimeMillis();
UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService("usagestats");
List<UsageStats> queryUsageStats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, endTime);
for (UsageStats us : queryUsageStats) {
totalTime += (int) us.getTotalTimeInForeground() / 60000;
}
if (totalTime > timeLimit) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext());
notificationManager.notify(NOTIFICATION_ID, builder.build());
Log.d(TAG, "Notification Sent");
jobCancelled = true;
}
Log.d(TAG, "total time: " + totalTime);
Log.d(TAG, "time limit: " + timeLimit);
}
}).start();
jobFinished(jobParameters, false);
return true;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
jobCancelled = true;
Log.d(TAG, "Job cancelled");
return false;
}
}
I am creating a school application in which when i visit there for
marketing i have to submit a report every time. If visit is
Successful then there is no issue if visit is unsuccessful then i
have to reschedule my meeting for next visit. When i set date and
time for my next meeting it should remind me in early morning by
sending a notification and it should alarm at that time so i can get
reminder. here is my code for report Activity please help me
private void sendNotificationDetailsTwo() {
/* Calendar firingCal = Calendar.getInstance();
Calendar currentCal = Calendar.getInstance();
firingCal.set(Calendar.HOUR_OF_DAY, 8); // At the hour you wanna fire
firingCal.set(Calendar.MINUTE, 30); // Particular minute
firingCal.set(Calendar.SECOND, 0); // particular second
Long intendedTime = firingCal.getTimeInMillis();
if (firingCal.compareTo(currentCal) < 0) {
firingCal.add(Calendar.DAY_OF_MONTH, 1);
} else {
for (int i = 0; i < 10; ++i) {
Intent newIntentTwo = new Intent(Report_Activity.this, MyReceiver.class);
final int intent_id_two = (int) System.currentTimeMillis();
newIntentTwo.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
Bundle bundle = new Bundle();
bundle.putString("date", str_view_date);
bundle.putString("time", str_view_time);
bundle.putString("school_name", str_show_school_name);
bundle.putInt("intent_id", intent_id_two);
newIntentTwo.putExtras(bundle);
AlarmManager alarmManager = (AlarmManager) Report_Activity.this.getSystemService(Report_Activity.this.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(Report_Activity.this, intent_id_two, newIntentTwo, PendingIntent.FLAG_ONE_SHOT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime, AlarmManager.INTERVAL_DAY, pendingIntent);
}
}*/
/*alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); alarmIntent = new Intent(context of current file, AlarmReceiver1.class); // AlarmReceiver1 = broadcast receiver
pendingIntent = PendingIntent.getBroadcast( Menu.this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmIntent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
alarmManager.cancel(pendingIntent);
Calendar alarmStartTime = Calendar.getInstance();
Calendar now = Calendar.getInstance();
alarmStartTime.set(Calendar.HOUR_OF_DAY, 8);
alarmStartTime.set(Calendar.MINUTE, 00);
alarmStartTime.set(Calendar.SECOND, 0);
if (now.after(alarmStartTime)) {
Log.d("Hey","Added a day");
alarmStartTime.add(Calendar.DATE, 1);
}
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmStartTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Log.d("Alarm","Alarms set for everyday 8 am.");*/
Calendar firingCal = Calendar.getInstance();
Calendar now = Calendar.getInstance();
firingCal.set(Calendar.HOUR_OF_DAY,15);
firingCal.set(Calendar.MINUTE,25);
firingCal.set(Calendar.SECOND,0);
while(now.getTimeInMillis()>firingCal.getTimeInMillis()){
firingCal.add(Calendar.DATE,1);
}
Intent myInten = new Intent(Report_Activity.this,MyReceiver.class);
final int intent_id_two = (int) System.currentTimeMillis();
myInten.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
Bundle bundle = new Bundle();
bundle.putString("date", str_view_date);
bundle.putString("time", str_view_time);
bundle.putString("school_name", str_show_school_name);
bundle.putInt("intent_id", intent_id_two);
myInten.putExtras(bundle);
//final int intent_id_two = (int) System.currentTimeMillis();
PendingIntent myPendingIntent = PendingIntent.getBroadcast(Report_Activity.this,intent_id_two,myInten,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)Report_Activity.this.getSystemService(Report_Activity.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,firingCal.getTimeInMillis(),2000,myPendingIntent);
}
MyAlarmService.java
public class MyAlarmService extends Service {
private NotificationManager notificationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
boolean alarm =(PendingIntent.getBroadcast(this,0,new Intent("Alarm"),PendingIntent.FLAG_NO_CREATE)==null);
if(alarm){
Intent mintent =new Intent("Alarm");
PendingIntent mpendingIntent = PendingIntent.getBroadcast(this,0,mintent,0);
Calendar mcalender = Calendar.getInstance();
mcalender.setTimeInMillis(System.currentTimeMillis());
mcalender.add(Calendar.SECOND,3);
AlarmManager malarmmanager = (AlarmManager)getSystemService(ALARM_SERVICE);
malarmmanager.setRepeating(AlarmManager.RTC_WAKEUP,mcalender.getTimeInMillis(),6000,mpendingIntent);
}
}
}
MyReceiver.java
public class MyReceiver extends BroadcastReceiver {
int MID = 0;
int m = (int) ((new Date().getTime() / 1000L) % Integer.MAX_VALUE);
String date, time, school_name;
PendingIntent pendingIntent;
int intent_id;
#Override
public void onReceive(Context context, Intent intent) {
// long when = System.currentTimeMillis();
Bundle bundle = intent.getExtras();
date = bundle.getString("date");
time = bundle.getString("time");
school_name = bundle.getString("school_name");
intent_id = bundle.getInt("intent_id");
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
//final int intent_id = (int) System.currentTimeMillis();
pendingIntent = PendingIntent.getActivity(context, intent_id, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = (NotificationCompat.Builder) new NotificationCompat.Builder(context)
.setContentTitle("Notification From Dextro")
.setContentText("Meeting Schedule at " + school_name + " on " + date + " and time is " + time)
.setSmallIcon(R.mipmap.dextro_customerlogo)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setSound(alarmSound)
.setTicker("Notification From Dextro")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("Meeting Schedule at " + school_name + " on " + date + " and time is " + time))
.setVibrate(new long[]{100, 100, 100, 100});
notificationManager.notify(m, builder.build());
MID++;
}
}
1. In Simple way When i Reschedule my Work it should get notify me on
next morning with alarm
try this
.setVibrate(new long[]{0, 2000, 500, 2000, 500, 2000, 500});
try {
Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.bells_bells_bells); //your sound file name from Raw folder
.setSound(uri);
} catch (Exception e) {
e.printStackTrace();
}
I currently have daily repeating notifications which repeat at 6pm each day. What I want to do is instead of 6pm, show the notification when a event is about to start. I have a events arraylist, and it contains dates and times, would this be possible. Below is how I am currently showing the notifications.
This is in my main activity
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 18);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
Intent intent1 = new Intent(MainActivity.this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0,intent1, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
and this is in my broadcast_reciever class
public class AlarmReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, EVentsPerform.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(
context).setSmallIcon(R.drawable.applogo)
.setContentTitle("Alarm Fired")
.setContentText("Events To be PErformed").setSound(alarmSound)
.setAutoCancel(true).setWhen(when)
.setContentIntent(pendingIntent)
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
notificationManager.notify(MID, mNotifyBuilder.build());
MID++;
}
}
I am not sure how to set the time so it repeats when and if there is a event. Any pointers and help with be appreciated. Thanks
You can set an alarm for each event. read all the events times from your database and then set individual alarms for those events. Instead of setRepeating use this. The set alarm variant is for different Android versions to wake up the phone from sleep.
private void setAlarm(Long dateInMillis) {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= 23) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, dateInMillis, pi);
} else if (Build.VERSION.SDK_INT >= 19) {
am.setExact(AlarmManager.RTC_WAKEUP, dateInMillis, pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, dateInMillis, pi);
}
}
dateInMillis is the Calender.getInstance().getTimeInMillis() for the time you want to set the alarm for. So i hope you have a long stored in your database which is that value to make your life easier for this
public ArrayList<String> getAlarms() {
SQLiteDatabase db;
ArrayList<String> result = new ArrayList<String>();
String myPath = DATABASE_PATH + DATABASE_NAME;
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
selectQuery = "SELECT * FROM TABLE";
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
result.add(cursor.getString(cursor.getColumnIndex("WhateverYourColumnIs")));
while (cursor.moveToNext()) {
result.add(cursor.getString(cursor.getColumnIndex("WhateverYourColumnIs")));
}
}
cursor.close();
db.close();
return result;
}
You can convert the string to a Long
DatabaseHelper db = new DatabaseHelper();
ArrayList<String> alarms = db.getAlarms()
for(String alarm : alarms){
try{
setAlarm(Long.parseLong(alarm));
}catch(NumberFormatException nfe){
//Not a number
}
}
something like that
private Long calendarMillis(String date, String time){
Long result;
//Do A bunch of stuff to get the information to fill in below from what you bring in.
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
//...Calendar.HOUR, Calendar.MONTH, Calendar.DAY
c.set(Calendar.MINUTE, minute);
result = c.getTimeInMillis();
return result;
}
public class NotificationInformation{
Long alarmTime;
String name;
public void NotificationInformation(){
}
public void NotificationInformation(NotificationInformation ni){
this.name = ni.getName();
this.alarmTime = ni.getAlarmTime();
}
//getters and setters
public void setAlarmTime(Long alarmTime){
this.alarmTime = alarmTime;
}
public void setName(String name){
this.nime = nime;
}
public Long getAlarmTime(){
return alarmTime;
}
public String getName(){
return name;
}
}
public class DatabaseHandler extends SQLiteOpenHelper {
private static final String DATABASE_PATH = "/data/data/YOUR_PACKAGE_HERE/databases/";
private static final String DATABASE_NAME = "YOUR_DATABASE.db";
private static final int DATABASE_VERSION = 1;
private SQLiteDatabase myDataBase = null;
private final Context myContext;
Context context = null;
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.myContext = context;
// TODO Auto-generated constructor stub
myDataBase = this.getWritableDatabase();
myDataBase.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE IF NOT EXISTS INFO (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"alarmTime INTEGER," +
"name TEXT)");
}
public void addInfo(long time, String name) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("alarmTime", time);
values.put("name", name);
db.insert("INFO", null, values);
db.close();
}
public ArrayList<NotificationInfo> getInfoAll() {
String selectQuery;
SQLiteDatabase db;
Cursor cursor;
NotificationInfo ni = new NotificationInfo();
ArrayList<NotificationInfo> result = new ArrayList<NotificationInfo>();
String myPath = DATABASE_PATH + DATABASE_NAME;
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
selectQuery = "SELECT * FROM INFO";
cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
ni.setAlarmTime(cursor.getLong(cursor.getColumnIndex("alarmTime"));
ni.setName(cursor.getLong(cursor.getColumnIndex("name"));
result.add(new NotificationInfo(ni));
while(cursor.moveToNext()){
ni.setAlarmTime(cursor.getLong(cursor.getColumnIndex("alarmTime"));
ni.setName(cursor.getLong(cursor.getColumnIndex("name"));
result.add(new NotificationInfo(ni));
}
}
cursor.close();
db.close();
return result;
}
}
public class AlarmActivity extends Activity{
//standard code for activity goes here
private void buttonClicked(){
Calendar c = Calendar.getInstance();
DatabaseHandler db = new Databasehandler(AlarmActivity.this);
ArrayList<NotificationInfo> alarms = db.getInfoAll();
db.close();
for(NotificationInfo ni : alarms){
c.setTimeInMillis(ni.getAlarmTime());
c.add(Calendar.MINUTE, -30);
setAlarm(c);
}
}
private void setAlarm(Long dateInMillis) {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= 23) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, dateInMillis, pi);
} else if (Build.VERSION.SDK_INT >= 19) {
am.setExact(AlarmManager.RTC_WAKEUP, dateInMillis, pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, dateInMillis, pi);
}
}
}
public class NotificationInformation{
Long alarmTime;
String name;
public void NotificationInformation(){
}
public void NotificationInformation(NotificationInformation ni){
this.name = ni.getName();
this.alarmTime = ni.getAlarmTime();
}
//getters and setters
public void setAlarmTime(Long alarmTime){
this.alarmTime = alarmTime;
}
public void setName(String name){
this.nime = nime;
}
public Long getAlarmTime(){
return alarmTime;
}
public String getName(){
return name;
}
}
Working with Reminders taking two dates from user, first Start Reminder Date and second End Reminder Date
I have successfully written a code to start a reminder, repeat the reminder and now I would like to know How can I remove the reminder when comes to End date from database ?
I know, I have to use something like below to cancel an alarm (to delete reminder from database) but don't know where to use same code to delete reminder based on End date provided with reminder, click on link to see Activity code
for (int i = IDmap.size(); i >= 0; i--) {
int id = IDmap.get(i);
// Get reminder from reminder database using id
Reminder temp = rb.getReminder(id);
// Delete reminder
rb.deleteReminder(temp);
// Delete reminder alarm
mAlarmReceiver.cancelAlarm(getApplicationContext(), id);
}
AlarmReceiver.java:
public class AlarmReceiver extends WakefulBroadcastReceiver {
AlarmManager mAlarmManager;
PendingIntent mPendingIntent;
#Override
public void onReceive(Context context, Intent intent) {
int mReceivedID = Integer.parseInt(intent.getStringExtra(ReminderEditActivity.EXTRA_REMINDER_ID));
// Get notification title from Reminder Database
ReminderDatabase rb = new ReminderDatabase(context);
Reminder reminder = rb.getReminder(mReceivedID);
String mTitle = reminder.getTitle();
// Create intent to open ReminderEditOldActivity on notification click
Intent editIntent = new Intent(context, ReminderEditActivity.class);
editIntent.putExtra(ReminderEditActivity.EXTRA_REMINDER_ID, Integer.toString(mReceivedID));
PendingIntent mClick = PendingIntent.getActivity(context, mReceivedID, editIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Create Notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
.setSmallIcon(R.drawable.ic_alarm_on_white_24dp)
.setContentTitle(context.getResources().getString(R.string.app_name))
.setTicker(mTitle)
.setContentText(mTitle)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(mClick)
.setAutoCancel(true)
.setOnlyAlertOnce(true);
NotificationManager nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
nManager.notify(mReceivedID, mBuilder.build());
}
public void setAlarm(Context context, Calendar calendar, int ID) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Put Reminder ID in Intent Extra
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(ReminderEditActivity.EXTRA_REMINDER_ID, Integer.toString(ID));
mPendingIntent = PendingIntent.getBroadcast(context, ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// Calculate notification time
Calendar c = Calendar.getInstance();
long currentTime = c.getTimeInMillis();
long diffTime = calendar.getTimeInMillis() - currentTime;
// Start alarm using notification time
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + diffTime,
mPendingIntent);
// Restart alarm if device is rebooted
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
public void setRepeatAlarm(Context context, Calendar calendar, int ID, long RepeatTime) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Put Reminder ID in Intent Extra
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(ReminderEditActivity.EXTRA_REMINDER_ID, Integer.toString(ID));
mPendingIntent = PendingIntent.getBroadcast(context, ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// Calculate notification timein
Calendar c = Calendar.getInstance();
long currentTime = c.getTimeInMillis();
long diffTime = calendar.getTimeInMillis() - currentTime;
// ensure the next alarm is in the future
while(diffTime < 0) {
diffTime += RepeatTime;
}
// Start alarm using initial notification time and repeat interval time
mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + diffTime,
RepeatTime , mPendingIntent);
// Restart alarm if device is rebooted
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
public void cancelAlarm(Context context, int ID) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Cancel Alarm using Reminder ID
mPendingIntent = PendingIntent.getBroadcast(context, ID, new Intent(context, AlarmReceiver.class), 0);
mAlarmManager.cancel(mPendingIntent);
// Disable alarm
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
}
BootReceiver.java:
public class BootReceiver extends BroadcastReceiver {
private String mTitle;
private String mTime;
private String mDate;
private String mRepeatNo;
private String mRepeatType;
private String mActive;
private String mRepeat;
private String[] mDateSplit;
private String[] mTimeSplit;
private int mYear, mMonth, mHour, mMinute, mDay, mReceivedID, mEndDay, mEndMonth, mEndYear;
private long mRepeatTime;
private String mEndDate;
private String[] mEndDateSplit;
private Calendar mCalendar, mEndCalendar;
private AlarmReceiver mAlarmReceiver;
// Constant values in milliseconds
private static final long milMinute = 60000L;
private static final long milHour = 3600000L;
private static final long milDay = 86400000L;
private static final long milWeek = 604800000L;
private static final long milMonth = 2592000000L;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
ReminderDatabase rb = new ReminderDatabase(context);
mCalendar = Calendar.getInstance();
mEndCalendar = Calendar.getInstance();
mAlarmReceiver = new AlarmReceiver();
List<Reminder> reminders = rb.getAllReminders();
for (Reminder rm : reminders) {
mReceivedID = rm.getID();
mRepeat = rm.getRepeat();
mRepeatNo = rm.getRepeatNo();
mRepeatType = rm.getRepeatType();
mActive = rm.getActive();
mDate = rm.getDate();
mTime = rm.getTime();
mEndDate = rm.getmEndDate();
mDateSplit = mDate.split("/");
mTimeSplit = mTime.split(":");
mEndDateSplit = mEndDate.split("/");
mDay = Integer.parseInt(mDateSplit[0]);
mMonth = Integer.parseInt(mDateSplit[1]);
mYear = Integer.parseInt(mDateSplit[2]);
mEndDay = Integer.parseInt(mEndDateSplit[0]);
mEndMonth = Integer.parseInt(mEndDateSplit[1]);
mEndYear = Integer.parseInt(mEndDateSplit[2]);
mHour = Integer.parseInt(mTimeSplit[0]);
mMinute = Integer.parseInt(mTimeSplit[1]);
mCalendar.set(Calendar.MONTH, --mMonth);
mCalendar.set(Calendar.YEAR, mYear);
mCalendar.set(Calendar.DAY_OF_MONTH, mDay);
mCalendar.set(Calendar.HOUR_OF_DAY, mHour);
mCalendar.set(Calendar.MINUTE, mMinute);
mCalendar.set(Calendar.SECOND, 0);
mEndCalendar.set(Calendar.MONTH, --mEndMonth);
mEndCalendar.set(Calendar.YEAR, mEndYear);
mEndCalendar.set(Calendar.DAY_OF_MONTH, mEndDay);
mEndCalendar.set(Calendar.HOUR_OF_DAY, mHour);
mEndCalendar.set(Calendar.MINUTE, mMinute);
mEndCalendar.set(Calendar.SECOND, 0);
// Cancel existing notification of the reminder by using its ID
// mAlarmReceiver.cancelAlarm(context, mReceivedID);
// Check repeat type
if (mRepeatType.equals("Daily")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Every 2 Days")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Every 3 Days")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Weekly")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milWeek;
} else if (mRepeatType.equals("Monthly")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milMonth;
}
// Create a new notification
if (mActive.equals("true")) {
if (mRepeat.equals("true")) {
mAlarmReceiver.setRepeatAlarm(context, mCalendar, mReceivedID, mRepeatTime);
} else if (mRepeat.equals("false")) {
mAlarmReceiver.setAlarm(context, mCalendar, mReceivedID);
}
}
}
}
}
}
UPDATED
#Override
public void onReceive(Context context, Intent intent) {
int mReceivedID = Integer.parseInt(intent.getStringExtra(ReminderEditActivity.EXTRA_REMINDER_ID));
// Get notification title from Reminder Database
ReminderDatabase rb = new ReminderDatabase(context);
Reminder reminder = rb.getReminder(mReceivedID);
String[] s = mEndDateSplit = mEndDate.split("/");
int mEndDay = Integer.parseInt(mEndDateSplit[0]);
int mEndMonth = Integer.parseInt(mEndDateSplit[1]);
int mEndYear = Integer.parseInt(mEndDateSplit[2]);
int mHour = Integer.parseInt(mTimeSplit[0]);
int mMinute = Integer.parseInt(mTimeSplit[1]);
Calendar mEndCalendar = Calendar.getInstance();
mEndCalendar.set(Calendar.MONTH, --mEndMonth);
mEndCalendar.set(Calendar.YEAR, mEndYear);
mEndCalendar.set(Calendar.DAY_OF_MONTH, mEndDay);
mEndCalendar.set(Calendar.HOUR_OF_DAY, mHour);
mEndCalendar.set(Calendar.MINUTE, mMinute);
mEndCalendar.set(Calendar.SECOND, 0);
String mRepeatNo = reminder.getRepeatNo();
if (mRepeatType.equals("Daily")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Every 2 Days")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Every 3 Days")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Weekly")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milWeek;
} else if (mRepeatType.equals("Monthly")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milMonth;
}
if(SystemClock.elapsedRealtime() < mEndCalendar.getTimeInMillis()) {
String mTitle = reminder.getTitle();
// Create intent to open ReminderEditOldActivity on notification click
Intent editIntent = new Intent(context, ReminderEditActivity.class);
editIntent.putExtra(ReminderEditActivity.EXTRA_REMINDER_ID, Integer.toString(mReceivedID));
PendingIntent mClick = PendingIntent.getActivity(context, mReceivedID, editIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Create Notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
.setSmallIcon(R.drawable.ic_alarm_on_white_24dp)
.setContentTitle(context.getResources().getString(R.string.app_name))
.setTicker(mTitle)
.setContentText(mTitle)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(mClick)
.setAutoCancel(true)
.setOnlyAlertOnce(true);
NotificationManager nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
nManager.notify(mReceivedID, mBuilder.build());
}
if (reminder.getRepeat().equals("true")) {
if( SystemClock.elapsedRealtime() + mRepeatTime > mEndCalendar.getTimeInMillis()){
// The next alert will happen after the end time, cancel it and delete it from the database.
cancelAlarm(context, mReceivedID);
rb.deleteReminder(reminder);
}
} else {
// The alert isn't set to be repeated, cancel and delete it from the database.
cancelAlarm(context, mReceivedID);
rb.deleteReminder(reminder);
}
}
Here is what I've meant in the comment I've posted.
public class AlarmReceiver extends WakefulBroadcastReceiver {
...
#Override
public void onReceive(Context context, Intent intent) {
ReminderDatabase rb = new ReminderDatabase(context);
Reminder reminder = rb.getReminder(mReceivedID);
.......
if(rm.getRepeat().equals("true")){
String[] s = mEndDateSplit = mEndDate.split("/");
int mEndDay = Integer.parseInt(mEndDateSplit[0]);
int mEndMonth = Integer.parseInt(mEndDateSplit[1]);
int mEndYear = Integer.parseInt(mEndDateSplit[2]);
int mHour = Integer.parseInt(mTimeSplit[0]);
int mMinute = Integer.parseInt(mTimeSplit[1]);
Calendar mEndCalendar = Calendar.getInstance();
mEndCalendar.set(Calendar.MONTH, --mEndMonth);
mEndCalendar.set(Calendar.YEAR, mEndYear);
mEndCalendar.set(Calendar.DAY_OF_MONTH, mEndDay);
mEndCalendar.set(Calendar.HOUR_OF_DAY, mHour);
mEndCalendar.set(Calendar.MINUTE, mMinute);
mEndCalendar.set(Calendar.SECOND, 0);
String mRepeatNo = rm.getRepeatNo();
if (mRepeatType.equals("Daily")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Every 2 Days")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Every 3 Days")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milDay;
} else if (mRepeatType.equals("Weekly")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milWeek;
} else if (mRepeatType.equals("Monthly")) {
mRepeatTime = Integer.parseInt(mRepeatNo) * milMonth;
}
if(SystemClock.elapsedRealtime() + mRepeatTime > nEndCalendar.getTimeInMills()) {
// The next alert will happen after the end time, cancel it and delete it from the database.
cancelAlarm(context, mReceivedID);
rb.deleteReminder(mReceivedID);
}
}else{
// The alert isn't set to be repeated, cancel and delete it from the database.
cancelAlarm(context, mReceivedID);
rb.deleteReminder(mReceivedID);
}
}
}
Check out my app on Google Play:
Code has been updated to use suggestions given by answer, however, still running into some problems...
I am using a BroadCast Receiver within a service to get metadata from Spotify (an external application). However, Spotify is unique in the fact that it sends the following intent-actions:
metadatachanged which contains the song's artist, track, length, etc.
playbackstatechanged which contains a boolean value for "playing" and an integer value for the current position in the song.
However, I have been running into some problems. I have written the following code:
public class BackgroundService extends Service {
AudioManager am;
int positionInMs;
double eps = 5000;
String trackId = null;
String lastTrackId = null;
int lastPlayTime = 0;
int addSeconds = 0;
int trackLengthInSec = 0;
boolean playing = false;
boolean timerStarted = false;
void startTimer(){
timerStarted = true;
new Timer(true).scheduleAtFixedRate(
new TimerTask() {
#Override
public void run() {
if(playing) {
if(lastTrackId == null) {
lastTrackId = trackId;
}else if (!lastTrackId.equals(trackId)) {
addSeconds = 1;
playing = true;
lastPlayTime = positionInMs;
// Track changed. Reset counter.
}else{
addSeconds++; // Increment counter.
}
checkMuteStatus(trackLengthInSec, lastPlayTime + addSeconds * 1000 // multiply by 1000 as we're counting in seconds
);
}
Log.e("-------:", "Last Play Time: " + String.valueOf(lastPlayTime));
Log.e("-------:", "Track Length: " + String.valueOf(trackLengthInSec));
Log.e("-------:", "Current Position: " + String.valueOf(lastPlayTime + addSeconds * 1000));
}
},
1000, // Wait a second before first run
1000 // Runs every second
);
}
#Override
public void onCreate() {
super.onCreate();
am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
IntentFilter filter;
filter = new IntentFilter();
filter.addAction("com.spotify.music.playbackstatechanged");
filter.addAction("com.spotify.music.metadatachanged");
filter.addAction("com.spotify.music.queuechanged");
Notification notification = new Notification();
startForeground(1, notification);
registerReceiver(receiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) throws NullPointerException {
long timeSentInMs = intent.getLongExtra("timeSent", 0L);
String action = intent.getAction();
if (action.equals(BroadcastTypes.METADATA_CHANGED)) {
trackId = intent.getStringExtra("id");
String artistName = intent.getStringExtra("artist");
String albumName = intent.getStringExtra("album");
String trackName = intent.getStringExtra("track");
trackLengthInSec = intent.getIntExtra("length", 0);
Log.e("STATUS:", trackName);
Log.e("STATUS:", artistName);
Log.e("STATUS:", albumName);
Log.e("STATUS:", "TRACK LENGTH: " + String.valueOf(trackLengthInSec));
Log.e("STATUS:", trackId);
Log.e("STATUS:", "POSITION: " + String.valueOf(positionInMs));
if(!timerStarted) {
startTimer();
}
//---------------------- IF PAUSED OR SONG CHANGED---------------------
} else if (action.equals(BroadcastTypes.PLAYBACK_STATE_CHANGED)) {
playing = intent.getBooleanExtra("playing", false);
positionInMs = intent.getIntExtra("playbackPosition", 0);
lastPlayTime = positionInMs;
addSeconds = 0; // Reset counter as we've now got the current position.
if(!timerStarted) {
startTimer();
}
}
}
};
void checkMuteStatus(double trackLength, double currentTime) {
if (Math.abs(trackLength - currentTime) < eps) {
mute(am);
Log.e("STATUS:", "MUTED");
addSeconds = 0;
lastPlayTime = 0;
} else {
unMute(am);
Log.e("STATUS:", "NOT MUTED");
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("STATUS:", "In onDestroy");
unregisterReceiver(receiver);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
static final class BroadcastTypes {
static final String SPOTIFY_PACKAGE = "com.spotify.music";
static final String PLAYBACK_STATE_CHANGED = SPOTIFY_PACKAGE + ".playbackstatechanged";
static final String METADATA_CHANGED = SPOTIFY_PACKAGE + ".metadatachanged";
}
public void mute(AudioManager audioManager){
audioManager.setStreamMute(audioManager.STREAM_SYSTEM, true);
audioManager.setStreamMute(AudioManager.STREAM_NOTIFICATION, true);
audioManager.setStreamMute(AudioManager.STREAM_ALARM, true);
audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
audioManager.setStreamMute(AudioManager.STREAM_RING, true);
}
public void unMute(AudioManager audioManager){
audioManager.setStreamMute(audioManager.STREAM_SYSTEM,false);
audioManager.setStreamMute(AudioManager.STREAM_NOTIFICATION, false);
audioManager.setStreamMute(AudioManager.STREAM_ALARM, false);
audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false);
audioManager.setStreamMute(AudioManager.STREAM_RING, false);
}
}
Which all works perfectly in getting the data, etc.
Essentially I am attempting to mute a user's phone when the length of the song subtracted from the current playback time in the song is less than a certain number. This basically allows me to have the device muted when an ad is playing, and unmuted when a new song is started. The only problem I consistently come across is that I can only access the current position in the song when the play state is changed. This essentially means that in order for my app to check whether it should mute the device, Spotify must first be paused so that the current playback time is updated.
So my question is, how can I keep my current playback time up-to-date so that my muting functionality is able to work? Is there a way I can implement a "timer" of sorts which kicks in after I receive a value for the current playback time and then increments the time until next update?
You could start a timer that executes every second when a song is played and use it to keep track of the elapsed seconds since.
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) throws NullPointerException {
long timeSentInMs = intent.getLongExtra("timeSent", 0L);
String action = intent.getAction();
if (action.equals(BroadcastTypes.METADATA_CHANGED)) {
trackId = intent.getStringExtra("id");
String artistName = intent.getStringExtra("artist");
String albumName = intent.getStringExtra("album");
String trackName = intent.getStringExtra("track");
trackLengthInSec = intent.getIntExtra("length", 0);
Log.e("STATUS:", trackName);
Log.e("STATUS:", artistName);
Log.e("STATUS:", albumName);
Log.e("STATUS:", "TRACK LENGTH: " + String.valueOf(trackLengthInSec));
Log.e("STATUS:", trackId);
Log.e("STATUS:", "POSITION: " + String.valueOf(positionInMs));
// the new track id is always updated just before the next song is played
// so we can safely assume that the ad has finished playing and it's time to unmute
unMute(am);
// reset & resume the timer
lastPlayTime = 0;
addSeconds = 0;
currentlyAdPlaying = false;
if(!timerStarted)
startTimer();
//---------------------- IF PAUSED OR SONG CHANGED---------------------
} else if (action.equals(BroadcastTypes.PLAYBACK_STATE_CHANGED)) {
playing = intent.getBooleanExtra("playing", false);
positionInMs = intent.getIntExtra("playbackPosition", 0);
// this is just needed to correct an eventually existing offset from the real time.
lastPlayTime = positionInMs;
addSeconds = 0; // Reset counter as we've now got the current position.
checkMuteStatus(trackLengthInSec, positionInMs);
}
}
};
String trackId = null;
String lastTrackId = null;
int lastPlayTime = 0;
int addSeconds = 0;
int trackLengthInSec = 0;
boolean playing = false;
boolean timerStarted = false;
boolean currentlyAdPlaying = true;
void startTimer(){
timerStarted = true;
new Timer(true).scheduleAtFixedRate(
new TimerTask() {
#Override
public void run() {
if(playing && !currentlyAdPlaying) {
if(lastTrackId == null)
lastTrackId = trackId;
if(lastTrackId != trackId){
lastTrackId = trackId;
addSeconds = 1; // Track changed. Reset counter.
} else {
addSeconds++; // Increment counter.
}
checkMuteStatus(
trackLengthInSec,
lastPlayTime + addSeconds * 1000
);
}
}
},
1000, // Wait a second before first run
1000 // Runs every second
);
}
void checkMuteStatus(double trackLength, double currentTime) {
// trackLength is in seconds, but currentTime in MS.
// So we should be changing trackLength to MS as well, right?
trackLength *= 1000;
if (Math.abs(trackLength - currentTime) < eps) {
mute(am);
Log.e("STATUS:", "MUTED");
// pause the timer, for an ad is playing.
currentlyAdPlaying = true;
} else {
unMute(am);
Log.e("STATUS:", "NOT MUTED");
}
}
Basically the timer runs every second (starting when an ad has finished playing) and then increments a counter as long as the song isn't paused. On reaching the end of the song the timer is suspended as an ad will be played next. Once the ad has finished playing, the timer is reset and resumed again.
With this method you might be off by half a second or so, consider decreasing the timer interval if necessary to get a higher resolution (don't forget to adjust the multiplier though).
Edit:
The code above won't notice the user changing the track mid-song, as no broadcasts are sent on that occasion. A workaround might be to add a muting button using notifications (eg. in combination with FLAG_NO_CLEAR and FLAG_ONGOING_EVENT).