I have a BroadcastReceiver
called AlarmReceiver
that Toast
s "alarm worked". I'm trying to set up a repeating PendingIntent
to trigger AlarmReceiver
at 5:45 and 17:30, but I see "alarm worked" after few seconds of starting the app. Why is the PendingIntent
getting sent immediately?
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, 05);
cal1.set(Calendar.MINUTE, 45);
cal1.set(Calendar.SECOND, 00);
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.HOUR_OF_DAY, 17);
cal2.set(Calendar.MINUTE, 30);
cal2.set(Calendar.SECOND, 00);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(),cal2.getTimeInMillis(), pi);
Toast.makeText(this, "Alarm set", Toast.LENGTH_LONG).show();
}
}
AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm worked.", Toast.LENGTH_LONG).show();
}
but I see "alarm worked" after few seconds of starts of my app.
I believe you are receiving the first alarm just fine.
But you believe it is not repeating. This wrong, it will repeat... once every ~43 years. You are using the third parameter of setRepeating
incorrectly, try:
Calendar cal1 = Calendar.getInstance(); // Now
cal1.add(Calendar.SECONDS, 5); // Change to five seconds from now
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
cal1.getTimeInMillis(),
10000, /* Repeat every 10 seconds */
pi);
The third parameter is an interval. This code creates an alarm that goes off in 5 seconds, then repeats every 10 seconds. By using cal2
you are accidentally setting the interval to almost 43 years.
To set two different alarms use:
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, 05);
cal1.set(Calendar.MINUTE, 45);
cal1.set(Calendar.SECOND, 00);
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.HOUR_OF_DAY, 17);
cal2.set(Calendar.MINUTE, 30);
cal2.set(Calendar.SECOND, 00);
// Test if the times are in the past, if they are add one day
Calendar now = Calendar.getInstance();
if(now.after(cal1))
cal1.add(Calendar.HOUR_OF_DAY, 24);
if(now.after(cal2))
cal2.add(Calendar.HOUR_OF_DAY, 24);
// Create two different PendingIntents, they MUST have different requestCodes
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent morningAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
PendingIntent eveningAlarm = PendingIntent.getBroadcast(getApplicationContext(), 1, intent, 0);
// Start both alarms, set to repeat once every day
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), DateUtils.DAY_IN_MILLIS, morningAlarm);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), DateUtils.DAY_IN_MILLIS, eveningAlarm);
As Sam's post says, you aren't using the right triggerAtMillis
and intervalMillis
. I think you are telling it to trigger at 5 am on the current day, which is likely in the past, in which case the documentation says that the
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.HOUR, 5);
cal1.add(Calendar.MINUTE, 45);
long interval = 17 * 60 * 60 * 1000; // 17 hours converted to milliseconds
interval += 30 * 60 * 1000; // 30 minutes converted to milliseconds
Intent intent = new Intent(this, TestAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), interval, pi);
is probably what you want to do instead.
EDIT (more explanation):
cal1.add(Calendar.HOUR, 5);
takes the current date and time and increases it by 5 hours, so the result is that the repeating PendingIntent
will begin 5 hours and 45 minutes from the current time on this date. and the interval
says that it will send the second and subsequent PendingItent
s every 17 hours and 30 minutes from then (where then is 5 hours and 45 minutes from now).
If you want to set the start to be 5:45 am, but don't want it to be sent immediately (unless it happens to be exactly 5:45 am at the moment). then you will want to set do:
cal1.set(Calendar.HOUR, 5);
cal1.set(Calendar.MINUTE, 45);
cal1.set(Calendar.SECOND, 0);
// Current time is after 5:45 am, don't start until tomorrow at 5:45
if (Calendar.getInstance().after(cal1))
cal1.add(Calendar.DAY_OF_YEAR, 1)
Alternatively, you can compute the interval from that time to decide when it would be triggered next assuming it had already been started at 5:45, but that would take a bit more work to compute.