I have created a event app that accepts alarms both individual and repeating. There is a glitch where if the app is active when the alarm goes off, not one, but two alarms will alert (indicative by the "overlapping" of alarm music offset by approx. 1 second)
However, if the app is killed, ie. onDestroy() only, there will be one and only one alarm
Is anyone familiar with this problem?
(I would post code but it appears a logical flaw with the alarm system...)
The scheduling of alarms:
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Testing adding the alarm date to this
Calendar alarmSchedule = Calendar.getInstance();
// Setting the time:
alarmSchedule.set(Calendar.HOUR, getAlarmTime().get(Calendar.HOUR));
alarmSchedule.set(Calendar.MINUTE, getAlarmTime().get(Calendar.MINUTE));
alarmSchedule.set(Calendar.SECOND, 0);
alarmSchedule.set(Calendar.YEAR, alarmDate.get(Calendar.YEAR));
alarmSchedule.set(Calendar.MONTH, alarmDate.get(Calendar.MONTH));
alarmSchedule.set(Calendar.DAY_OF_MONTH, alarmDate.get(Calendar.DAY_OF_MONTH));
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmSchedule.getTimeInMillis(), pendingIntent);
I met the problem two month ago, same as
two alarms will alert (indicative by the "overlapping" of alarm music offset by approx. 1 second)
alarm start time cause the problem
am.set(type, triggerAtMillis, operation);
am.setRepeating(type, triggerAtMillis, intervalMillis, operation)
if the type is RTC or RTC_WAKEUP the triggerAtMillis should be System.currentTimeMillis() + delay
if the type is ELAPSED_REALTIME or ELAPSED_REALTIME_WAKEUP the triggerAtMillis should be SystemClock.elapsedRealtime() + delay
Related
I want to trigger a daily alarm in my application. I can see the alarm being triggered daily at the correct time for 2 or 3 days but it does not trigger after that. For example if I set alarm to trigger at 08:00 AM, it will trigger at 8 AM daily for 2 or 3 days and after that there is no alarm triggered. There is no app crashing or anything, it simply does not trigger. I have a BroadcastReceiver registered (in AndroidManifest.xml) for this alarm and i can see logs being printed daily at the correct time but only for 2 or 3 days. After that there is no activity and the app just seems to die down.
Please find my code below :
final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final long intervalDay = 60*60*24*1000L;
final long alarmTime = calendar.getTimeInMillis();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime, intervalDay, pendingIntent);
I have also used alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime, AlarmManager.INTERVAL_DAY, pendingIntent); but it did not make any difference (didnt expect it to make any though).
I do not want to use alarmManager.setInexactRepeating() as it does not trigger the alarm at exact time but there is slight delay.
Any help appreciated !!
Thanks.
That's because android cannot hold the alarm content for more than 2-3 days. Though there is no sure shot solution that i know.
I fixed it by cancelling and resetting alarm everytime alarm is triggered.
Something like this.
Instead of using setRepeat use set or setExact to trigger for once:
if(android.os.Build.VERSION.SDK_INT<Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmtime, pendingIntent);
} else {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, alarmtime, pendingIntent);
}
Then in onRecieve() method of your alarmReciever after performing your task, reset the alarm again for next followed by cancelling all pending intents:
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), reminderModal.get_remindID(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
pendingIntent.cancel();
Hope it helps.
I have written the following AlarmManager to start a Service which will download a file at specified interval:
Calendar updateTime = Calendar.getInstance();
updateTime.setTimeZone(TimeZone.getDefault());
updateTime.set(Calendar.HOUR_OF_DAY, 7);
Intent downloader = new Intent(mActivity, FileDownloadService.class);
downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mActivity, 0, downloader, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
From the other part of the application, I get the value for repeating interval to run the Service. The value for repeating interval change on daily basis.
How can we change the AlarmManager interval at runtime as the above code will be executed only once?
For example, on day 1 I want the repeating interval to be 15 minutes and on day 2 I want the interval to be 2 hours.
How can I change the repeating interval dynamically?
Store the value 15 minutes inside your pending intent as an extra. When your code gets triggered by the alarm manager, get the current value, increment it as per your needs and reset the extra in the intent which holds the value.
Edit : Use alarmManager.set(int type, long triggerAtMillis, PendingIntent operation); at every new invocation of your code.
I am creating a clock application that has alarm feature too. The time is showing up properly and I am also setting multiple alarm properly.
I am creating multiple alarm using different id and also saving the same into Database so that I can view the list of alarms in a listview. Now I am trying to set ON and OFF functionality for my alarm. I have a problem there.
On itemclick if alarm is ON it switches OFF with the help of:
Intent intent = new Intent(Main.this,TaskRecieverForAlarm.class);
PendingIntent pi = PendingIntent.getBroadcast(Main.this, Integer.parseInt(cont[0]), intent, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.cancel(pi);
The above code cancels the alarms perfectly fine.
To switch ON the alarm I am using:
Intent intent = new Intent(Main.this, TaskRecieverForAlarm.class);
intent.putExtra("AlarmDate", cont[1]);
intent.putExtra("key", Integer.parseInt(cont[0]));
PendingIntent sender = PendingIntent.getBroadcast(Main.this, Integer.parseInt(cont[0]) , intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
if(type.equalsIgnoreCase("daily"))
{
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1440*60000 ,sender);
}
else if(type.equalsIgnoreCase("weekly"))
{
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender); am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 7*1440*60000 ,sender);
}
Now as soon as I click the OFF to ON, alarm triggers and calls the TASKReceiverFORAlarm (broadcast receiver) even though the alarm time is 4 or 5 hours from the current time. I am not sure where I am going wrong?
Can somebody help me out?
Thanks!
I think I found the answer here:
public void setRepeating (int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
Added in API level 1
Schedule a repeating alarm. Note: for timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler. If there is already an alarm scheduled for the same IntentSender, it will first be canceled.
Like set(int, long, PendingIntent), except you can also supply a rate at which the alarm will repeat. This alarm continues repeating until explicitly removed with cancel(PendingIntent). If the time occurs in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval.
If an alarm is delayed (by system sleep, for example, for non _WAKEUP alarm types), a skipped repeat will be delivered as soon as possible. After that, future alarms will be delivered according to the original schedule; they do not drift over time. For example, if you have set a recurring alarm for the top of every hour but the phone was asleep from 7:45 until 8:45, an alarm will be sent as soon as the phone awakens, then the next alarm will be sent at 9:00.
If your application wants to allow the delivery times to drift in order to guarantee that at least a certain time interval always elapses between alarms, then the approach to take is to use one-time alarms, scheduling the next one yourself when handling each alarm delivery.
Parameters
type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP}, RTC or RTC_WAKEUP.
triggerAtMillis time in milliseconds that the alarm should first go off, using the appropriate clock (depending on the alarm type).
intervalMillis interval in milliseconds between subsequent repeats of the alarm.
operation Action to perform when the alarm goes off; typically comes from IntentSender.getBroadcast().
The way you use that function is:
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1440*60000 ,sender);
Try this one:
//The only variable here is the desired hour of the alarm, which
// has to be obtained in milliseconds
long alarmSetAt = // The hour of the Alarm for the current date in milliseconds
long time = cal.getTimeInMillis() - alarmSetAt;
if(time > 0){
time = -time + cal.getTimeInMillis();
}
else{
time = time + cal.getTimeInMillis() + 1440*60000;
}
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1440*60000 ,sender);
I am starting my service using below code repeatedly. My service starts at 8am everyday. And AlarmManager repeates at every 1 min. I want to stop this sevice at 6pm. how can I do this ?
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent loggerIntent = PendingIntent.getBroadcast(this, 0,new Intent(this,AlarmReceiver.class), 0);
Calendar timeOff9 = Calendar.getInstance();
timeOff9.set(Calendar.HOUR_OF_DAY, 08);
timeOff9.set(Calendar.MINUTE, 00);
timeOff9.set(Calendar.SECOND, 00);
//--------------------------------------------------------------------------------------------------------------------
long duration = userinterval * 60 * 1000;
manager.setRepeating(AlarmManager.RTC_WAKEUP,timeOff9.getTimeInMillis(), duration, loggerIntent);
In order to cancel at 6pm exactly, I would consider 2 options:
Each time the alarm triggers (i.e. every 1 minute), check the time, and cancel if time is after 6PM.
Set a once-off alarm in AlarmManager to go off at 6PM exactly. In that alarm, cancel.
I prefer option 2 for simplicity, and modularity of each code block. So for me, I would use (2) in my proof-of-concept code, while working on the solution.
But option 1 is better from a resources point of view, as the Android system only needs to remember a single alarm. I would use (1) in my final production code.
This way of working is just my personal preference, and most ppl probably will say to use (1) right away from the start.
The details about cancelling are below...
As for how to cancel an alarm, you don't often beat an answer by #commonsware....
Below answer copied from How to cancel this repeating alarm?
Call cancel() on AlarmManager with an equivalent PendingIntent to the one you used with setRepeating():
Intent intent = new Intent(this, AlarmReceive.class);
PendingIntent sender = PendingIntent.getBroadcast(this,
0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(sender);
I have an alarm which I can schedule to go off at a certain time. The thing is, when I shedule it into the future, it works at exactly the minute I set it for. It works as it should. But the problem is, if I schedule it in the past, it goes off immediately.
For example, if it is now 3:30pm and I schedule it for 3:35pm, it fires at 3:35pm. But if it is 3:30pm and I schedule it for 3:25pm, it fires immediately since it is in the past.
What I want it to do is, if it is int he past, just ignore it until the interval time passes.
Here is the code:
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, ApplicationClass.AlertNotifyID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
long milliSeconds24Hours = 86400000; //86400000 which is 24 hours in milliseconds
am.setRepeating(AlarmManager.RTC_WAKEUP, GetNotificationTime(context), milliSeconds24Hours, sender);
You need to get it to check if the scheduled time is in the past, and if so set your alarm to start the next day.