This is the code I have so far
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
setRepeatingAlarm();
public void setRepeatingAlarm() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(this, TimeAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), (15 * 1000), pendingIntent);
}
}
This is all I am trying to accomplish: The alarm will not turn on until 30 seconds past every minute. Once you clear it, it wont comes back on until 30 seconds past the next minute. So if I open the app, and it is 25 second past the minute, it will activate status bar notification 5 second later. But if it is 40 seconds past, I will have to wait 50 more seconds (into the next minute). I am not sure how to use the Calendar function to attain this?
If I understand your requirement then you could try something like the following...
Calendar cal = Calendar.getInstance();
if (cal.get(Calendar.SECOND) >= 30)
cal.add(Calendar.MINUTE, 1);
cal.set(Calendar.SECOND, 30);
// Do the Intent and PendingIntent stuff
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 60 * 1000, pendingIntent);
If you check the documentation for AlarmManager, it says that RTC_WAKEUP use time relative to System.currentTimeMillis():
RTC_WAKEUP Alarm time in System.currentTimeMillis() (wall clock time in UTC), which will wake up the device when it goes off.
So simply modify your triggerAtTime parameter, for instance to start right away:
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 15 * 1000, pendingIntent);
Then the alarm will be repeatedly fire every 15 seconds.
Related
I'm working on alarm clock app. I've faced with one problem. I do not know how to set alarm for several days. I've already tried the code that is below but in log I saw this Wed Apr 06(didn't change any date so it should be nearest tuesday and friday). What do I do wrong? May be I should set alarm separately for every other day?
This is my code:
calendar.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY, Calendar.FRIDAY);
//calendar.add(Calendar.DAY_OF_WEEK,Calendar.FRIDAY);
Log.e("Point_1","Calendar " + calendar.getTime());
calendar.set(Calendar.HOUR_OF_DAY,timePicker.getCurrentHour());
calendar.set(Calendar.MINUTE,timePicker.getCurrentMinute());
Intent intent1 = new Intent(MyService_alarm.this,MyReceiver_Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MyService_alarm.this,intent.getIntExtra("Size", 1),intent1,0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 7 * 24 * 3600 * 1000, pendingIntent);
Thank you.
That is because you are logging the time before setting the hour and minutes from the time picker,
your code si working fine but to display the time that was set to the Alarm in your log you have to move the Log.e to after you set the Calendar to the hour and minute from your picker so your code should look like this :
calendar.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY, Calendar.FRIDAY);
//calendar.add(Calendar.DAY_OF_WEEK,Calendar.FRIDAY);
calendar.set(Calendar.HOUR_OF_DAY,timePicker.getCurrentHour());
calendar.set(Calendar.MINUTE,timePicker.getCurrentMinute());
Log.e("Point_1","Calendar " + calendar.getTime());
Intent intent1 = new Intent(MyService_alarm.this,MyReceiver_Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MyService_alarm.this,intent.getIntExtra("Size", 1),intent1,0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 7 * 24 * 3600 * 1000, pendingIntent);
Also since you are making an Alarm for several days it would be wise to save all the set alarms and to add a receiver to detect when the device has been booted since your alarms are cancelled on reboot and will need to be added again.
The line
calendar.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY, Calendar.FRIDAY);
is not correct. If you look at the documentation you will see that there is no such method.
By writing Calendar.DAY_OF_WEEK you are telling system that you are entering some value as day of the week. But instead of one specific day you are entering two. Calendar object is used to store one specific date.
Therefore, in order to get set alarms for several days, you need to set each of the alarms separately. For this reason you may create separate Calendar objects or reuse one by changing the time. However, you have same receiver class for both alarms. Therefore, you need to create different pending intents to make alarm manager differentiate them. For this reason I have shown you the example with different request_code.
calendar1.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
calendar2.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
calendar1.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour());
calendar1.set(Calendar.MINUTE, timePicker.getCurrentMinute());
calendar2.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour());
calendar2.set(Calendar.MINUTE, timePicker.getCurrentMinute());
Intent intent1 = new Intent(MyService_alarm.this, MyReceiver_Alarm.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(MyService_alarm.this, 1, intent1, 0);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(MyService_alarm.this, 2, intent1, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, calendar1.getTimeInMillis(), 7 * 24 * 3600 * 1000, pendingIntent1);
alarmManager.setRepeating(AlarmManager.RTC, calendar2.getTimeInMillis(), 7 * 24 * 3600 * 1000, pendingIntent2);
I am trying to trigger action everyday at 00:00:00 AM using AlarmManager but the problem is first time action is triggered quickly and then works as expected. First time, action triggers as soon as the code is run. Please see the following code:
private void setAlarmManagerForDateChange()
{
Intent intent = new Intent(this, DateTimeChangeReceiver.class);
intent.putParcelableArrayListExtra("names", names);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
999, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.AM_PM, Calendar.AM);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(),
24 * 60 * 60 * 1000, pendingIntent);
}
It action triggers before 00:00:00 AM for the first time. Please point out what is being missed. Thanks,
You're scheduling the alarm in the past, which causes the AlarmManager to fire instantly.
You take the current date (e.g. 05/29/14 20:08:32), and set the hour, minute and second to 0.
What you get is: 05/29/14 00:00:00.
What you actually want, is to add another day to get to 06/29/14 00:00:00.
calendar.add(Calendar.DAY, 1);
Hi,
I use the following code snippet to invoke an action after a delay using the AlarmManager. But the alarm is invoked immediately.
AlarmUtility.java
public void setAlarm(Context context) {
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, 1000 *24*3600,
1000 *24*3600, pi); // Millisec * Second * Minute
} // trying to first trigger the alarm after 24 hrs and repeat after 24 hours
Please let me know what is my error
1000 *24*3600 is definitely in the past and so, the alarm will trigger immediately:
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.
Instead get the current time then add 24 hours for the inital wakeup:
Calendar calendar = Calendar.getInstance();
calendar.add (Calendar.DATE,1);
long day = 1000 *24*3600;
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), day , pi);
u should use like this:
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+time, time, pi);
and if u r want to use 1000 *24*3600, then use (1000 *24*3600)L. because 1000 *24*3600 is larger than Integer.Max_value.
Upon first look the problem seems to be with
am.setRepeating(AlarmManager.RTC_WAKEUP, 1000 *24*3600,
1000 *24*3600, pi);
The second parameter triggerAtTime should point to a time, when the alarm should go off. It should not be a time interval.
Check the below sample:
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000 *24*3600,
1000 *24*3600, pi);
I have a BroadcastReceiver called AlarmReceiver that Toasts "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 PendingItents 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.
Here is the code that I used to set an alarm for my widget:
private static void setAlarm(Context context) {
Intent myIntent = new Intent(context, Widget.class);
myIntent.setAction(AUTO_UPDATE);
PendingIntent pendingIntent =
PendingIntent.getBroadcast(context, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Service.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 8);
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 8000,
pendingIntent);
}
but the problem is that even in the sleep mode, onReceive() is still triggered by the intent.
Although after using setInexactRepeating instead of setRepeating, the delays between calls get increased up to 1 minute in sleep mode, but that's still battery consuming.
I believe you are setting the alarm to trigger 8 seconds after the Calendar's time, which you have set 8 seconds ahead of the current time .. so you are setting the alarm to trigger instantly.
I don't see any reason you need a Calendar here. The calendar is just used to track the time 8 seconds in the future here:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 8);
The alarm is created to trigger every 8 seconds here:
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 8000,
pendingIntent);
The alarm continues to trigger every eight seconds.
I would try changing:
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 8000,
pendingIntent);
To:
alarmManager.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis(), 8000,
pendingIntent);
If you continue having problems, then maybe the interval is the problem. Try changing setRepeating() to set() to see if that's the case.