How to Set Recurring AlarmManager to execute code daily - android

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.
}

Related

AlarmManager set weekly alarm on a specified weekday time repeats on app open

I want to repeat a notification in android at a scheduled time in a specific day of the week (8:30am Saturday). I have set up the code and the alarm works (with the notification). The alarm need not wake up the device and fires the notification on next wake up.
Problem: The alarm is fired once every time the app is newly opened.
Tried different combinations but cant get it to work. Your help is much appreciated. Thank you.
MainActivity.java (OnCreate)
AndroidHelper ahelper= new AndroidHelper();
public static long rand_news_notify_freq= AlarmManager.INTERVAL_DAY * 7;
Calendar ca = Calendar.getInstance();
ca.set(Calendar.HOUR_OF_DAY,8);
ca.set(Calendar.MINUTE,30);
ca.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
ca.set(Calendar.SECOND, 0);
ca.set(Calendar.MILLISECOND, 0);
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
ahelper.setAlarms(alarmMgr, getApplicationContext(), RandomNewsNotification.class, ca, rand_news_notify_freq);
AndroidHelper.class
public class AndroidHelper{
public AndroidHelper()
{
}
public void setAlarms(AlarmManager alarmMgr, Context tctx, Class alarmClass, Calendar calendar, long freq)
{
Intent alarmIntent = new Intent(tctx, alarmClass);
PendingIntent pendingIntent = PendingIntent.getBroadcast(tctx, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
//alarmMgr.setRepeating(alarmMgr.RTC, calendar.getTimeInMillis(), freq, pendingIntent); // This is not working
alarmMgr.setInexactRepeating(alarmMgr.RTC, calendar.getTimeInMillis(), freq, pendingIntent); // This is not working too (same problem)
}
}
What needs to be changed?
I don't know you want to set exact repeating or inexact repeating. for exact repeating, you yourself should handle repeating with exact methods and don't use repeating methods of alaramManager like setInexactRepeating.
also consider if device is on Doze mode, alaram won't fire. so you should use setExactAndAllowWhileIdle method to guarantee that the alarms will execute.
you can see more detail on Android Developer document:
https://developer.android.com/training/scheduling/alarms

AlarmManager won't trigger in specific time

I've got a problem with the AlarmManager. I'm able to set up the Alarm with this code
private void setAlarm(long when) {
Intent intent = new Intent(NoteActivity.this, AlarmReceiver.class);
intent.putExtra("ID", note.getId());
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, PendingIntent.getBroadcast(NoteActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT));
Toast.makeText(getApplicationContext(),"Reminder set up", Toast.LENGTH_SHORT).show();
}
This code works well if I set long when = 5 * 1000; \\For example 5secs later, but if I use this code
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
long selectedDate = date.getTime();
long timeSince1970 = System.currentTimeMillis();
long timeForAlarm = selectedDate - timeSince1970;
Intent intent = new Intent(NoteActivity.this, AlarmReceiver.class);
intent.putExtra("ID", note.getId());
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeForAlarm, PendingIntent.getBroadcast(NoteActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT));
Toast.makeText(getApplicationContext(),"Reminder set for "+calendar.getTime().toString(), Toast.LENGTH_SHORT).show();
my alarm triggerd 2secs later. What I'm doing wrong? :/
I've tried AlarmManager.ELAPSED_REALTIME_WAKEUP and AlarmManager.RTC_WAKEUP but nothing changed.
Please do not check my question as duplicated. I didn't find something to try that solved my problem.
Assuming that you are working in Android Studio (if not - you must switch), click F1 while your text pointer is on set method and read description of AlarmManager::set.
Note: Beginning in API 19, the trigger time passed to this method is
treated as inexact: the alarm will not be delivered before this time,
but may be deferred and delivered some time later. The OS will use
this policy in order to "batch" alarms together across the entire
system, minimizing the number of times the device needs to "wake up"
and minimizing battery use. In general, alarms scheduled in the near
future will not be deferred as long as alarms scheduled far in the
future.
Instead of set use setExact
manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeForAlarm, PendingIntent.getBroadcast(NoteActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT));

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!

AlarmManager setRepeating disregards the interval

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.

Categories

Resources