AlarmManager setRepeating disregards the interval - android

I use this code to setup an alarm in our business application:
private void setupAlarm() {
final Context c = getApplicationContext();
final AlarmManager alarm =
(AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
final Intent i = new Intent(c, AlarmReceiver.class);
final PendingIntent sender =
PendingIntent.getBroadcast(c, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
final long startFromNow = System.currentTimeMillis()+10000;
final long timer = 5*60*1000;
alarm.setRepeating(AlarmManager.RTC_WAKEUP, startFromNow, timer, sender);
}
I cannot understand why the interval for the alarm is not respected. First alarm starts after 10 seconds (as expected), afterwards it starts every 2 minutes and a bit (122 seconds to 127 seconds), which is wrong. The interval is 5 minutes, or am I wrong?
I use this exact code in a simpler application: one activity that sets the repeating alarm and the receiver just creates a log. There it works.
What could make the AlarmManager act so different?
I have tried to:
use set() and in the alarm receiver use another set() for over 5 minutes: launch at 2 minutes
use setInexactRepeating() instead of setRepeating(): launch at 2 minutes
Any insight would be helpful. Thanks!

Immediate suggestion that comes to mind - make sure you don't set an alarm with the same intent and different value elsewhere. The intent need not be the same object, see the set methods documentation in AlarmManager.

Related

Use one alarm manager to cancel another

I am doing a reminder application. It will reminder for a duration at the interval of time. For example, remind every five minutes for an hour. In this case, I am trying to set two alarm. One is used to do the reminder for every five minutes, the other one is used to cancel the reminder alarm after one hour. Here is my codes.
private void createIntervalNotification(int reminder, int dhour, int dminute){ //reminder in min
int interval = (reminder)*60*1000;
AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+interval, interval, getPendingIntent(this,REMINDER_ID));
int duration = (dhour*60 + dminute)*60*1000;
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+duration,getPendingIntent(this,CANCEL_REMINDER_ID));
}
private static PendingIntent getPendingIntent(Context ctxt, int id) {
Intent intent1 = new Intent(ctxt, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(ctxt, id,intent1, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
I have some questions to do this(Set reminder of 5 mins for duration of 1 hour).
1) Can I do this with my method? Use one alarm to cancel another?
2) Can both alarm share a broadcastReceiver? If yes, how to differentiate it is invoked by which alarm?
3) Is it any other method can do this?
Cancelling an alarm is pretty much exactly the same as setting an alarm. You just call a different method to cancel on the AlarmManager than you do to create. Just make sure that the pending intent in the AlarmManager and the broadcast ID is identical.
Differentiate alarms by setting Extras on the Intent.

How to set alarm at exact time in KITKAT

I have set alarm to get trigger after 60 seconds. but the alarm is getting triggered after 80/90 seconds (But not exactly after 60 seconds). How can i set alarm to get trigger exact at specified time?
//calling method to set alarm after 60 seconds
startAlarm(context, 1, System.currentTimeMillis()+60000);
//method defination
public static void startAlarm(Context context, int timerType, long nextScheduledTime) {
EABLog.d(TAG, " ~~~INSIDE START ALARM~~~~~ "+timerType);
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(Constants.KEY_TIMER_TYPE, timerType);
intent.setAction(""+timerType);
PendingIntent pollPendingIntent = PendingIntent.getBroadcast(context,
timerType, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextScheduledTime,
pollPendingIntent);
EABLog.d(TAG, System.currentTimeMillis()+" ALARM IS SET AT "+nextScheduledTime+" TYPE :"+timerType);
}
//permission added in Android Manifest
<uses-permission android:name="android.permission.WAKE_LOCK"/>
As docs say about setExact - The alarm will be delivered as nearly as possible to the requested trigger time. So it is not as exact as you think :)
Look at public void setWindow (int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) methods 3rd parameter - windowLengthMillis The length of the requested delivery window, in milliseconds. The alarm will be delivered no later than this many milliseconds after windowStartMillis.
This might do the trick :)

Android: CountDownTimer vs AlarmManager

I have to run a piece of code every 5 minutes in my service. Will countdowntimer be killed since the app is not in foreground. If this is the case will alarmanager be better in running the code?
Thanks,
Sahil
I think especially if your code runs in a Service that an AlarmManager is the better alternative. You can use the AlarmManager to start your Service in a 5 minute interval like this:
Calendar calendar = Calendar.getInstance();
Intent intent = new Intent(context, YourService.class);
// Set action of Intent or add extras
long period = 5 * 60 * 1000; // 5 minutes
PendingIntent pendingIntent = PendingIntent.getService(context, alarmId, intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), period, pendingIntent);
If you want to stop your alarm you have to use the same alarmId so it would be best if you put that id in a constant. Also note that you have to restart your alarm every time the phone reboots!

Updating Android widgets every 1 minute

I'm writing an Android widget. I want to update it every 1-5 minutes to monitor data from web service but I discovered that android:updatePeriodMillis cannot be less than 30 minutes.
How can I obtain this result with a widget?
Register an AlarmManager service for every 1 min call.
final Intent intent = new Intent(context, UpdateService.class);
final PendingIntent pending = PendingIntent.getService(context, 0, intent, 0);
final AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pending);
long interval = 1000*60;
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),interval, pending);
However, pushing updates to app widgets is an expensive operation. Updating every 1 min would force your "update an app widget" code to be resident in memory which keeps running all of the time, and this will also eat up battery pretty significantly.
Use a Handler to sendMessageDelayed(..) a message or postDelayed(..) a Runner.
new Handler().postDelayed( new Runnable() {
public void run() { ... },
60000 /* one minute */
);

How to Set Recurring AlarmManager to execute code daily

I am currently trying to write alarm manager that will make an alarm go off within a specified period of time, daily. First I check to see if the user has had an alarm set for that for that day:
if ((User.getReminderTime(Home.this) > 0)
&& (dt.getDate() != today.getDate() || dt.getDay() != today
.getDay())) {
AppointmentManager.setFutureAppointmentCheck(this
.getApplicationContext());
User.setLongSetting(this, "futureappts", today.getTime());
}
Then I go and set the actual alarm to go off between 12 and 12:10 of the next day:
public static void setFutureAppointmentCheck(Context con) {
AlarmManager am = (AlarmManager) con
.getSystemService(Context.ALARM_SERVICE);
Date futureDate = new Date(new Date().getTime() + 86400000);
Random generator = new Random();
futureDate.setHours(0);
futureDate.setMinutes(generator.nextInt(10));
futureDate.setSeconds(0);
Intent intent = new Intent(con, FutureAppointmentReciever.class);
PendingIntent sender = PendingIntent.getBroadcast(con, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
am.set(AlarmManager.RTC_WAKEUP, futureDate.getTime(), sender);
}
Now I setup a test environment for this to go off every two minutes and it seems to be working fine, however when I deploy to an actual device, the reciever does not seem to be recieving the alarms. I thought it might be an issue with the device being asleep, so I added the power manager. But it still does not work:
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "keepAlive");
wl.acquire();
setFutureAppointments(context.getApplicationContext());
AppointmentManager.setFutureAppointmentCheck(context
.getApplicationContext());
User.setLongSetting(context.getApplicationContext(), "futureappts",
new Date().getTime());
wl.release();
Anyone see anything I am doing blatantly wrong or am I going about this incorrectly? thanks for any and all help.
I usually do something more along the lines of:
Intent i = new Intent(this, MyService.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.cancel(pi); // cancel any existing alarms
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
AlarmManager.INTERVAL_DAY, pi);
This way, you don't have to worry about re-setting the AlarmManager in your Service.
I usually run this bit of code when my app starts (onResume in my main activity) and in a BroadcastReceiver that is set up to receive BOOT_COMPLETED.
I've written a guide on creating Services and using the AlarmManager, which is based on my own experience and a few tips & tricks I picked off from watching a Google I/O talk. If you're interested, you can read it here.
To answer your question below, all I can do is quote the docs:
public void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation)
Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour. These alarms are more power-efficient than the strict recurrences supplied by setRepeating(int, long, long, PendingIntent), since the system can adjust alarms' phase to cause them to fire simultaneously, avoiding waking the device from sleep more than necessary.
Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time. In addition, while the overall period of the repeating alarm will be as requested, the time between any two successive firings of the alarm may vary. If your application demands very low jitter, use setRepeating(int, long, long, PendingIntent) instead.
In conclusion, it's not very clear. The docs only say that the alarm "may vary". However, it should be important for you to know that the first trigger might not occur for almost a full interval after that time.
This is working, this will shoot alarm after every 5 seconds
private void setRecurringAlarm() {
Logger.d(IConstants.DEBUGTAG, "Setting Recurring Alarm");
Calendar updateTime = Calendar.getInstance();
updateTime.set(Calendar.SECOND, 5);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
PendingIntent recurringDownload = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarms.cancel(recurringDownload);
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 1000 * 5, recurringDownload); //will run it after every 5 seconds.
}

Categories

Resources