I want the following:
The AlarmManager sends a daily intent to my AppWidgetProvider at midnight EXACTLY.
The Alarm must wake up the device.
Here is how I did it:
In my AppWidgetProvider subclass:
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
Log.d(LOG_TAG, "Widget Provider enabled. Starting timer");
//Setting the Calender object to midnight time.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 0);
calendar.add(Calendar.MINUTE, 0);
calendar.add(Calendar.HOUR, 0);
//The fired Intent
Intent intent = new Intent(CLOCK_WIDGET_UPDATE); //custom intent name
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1000*60*60*24, pendingIntent);
}
Although I think I did it right, this code doesn't work!
To test it, I changed 1000*60*60*24 with 10000 (10 sec) and updated a textView in the widget with random number. The random number never changed.
Any help will be appreciated !
I finally found the problem !
It seems that I need to set the AM_PM value too. When I print the calender using getTime().toLocaleString(), it was set to the next day but 12 hours later (12:00:00 PM).
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.AM_PM, Calendar.AM);
calendar.add(Calendar.DAY_OF_MONTH, 1);
This is a perfect setup for the Calender instance that will set the alarm to the next day at midnight (i.e. the nearest midnight). You just pass it to the setRepeating() method.
Thanks #CommonsWare
First, what you want is not strictly possible. Android is not a RTOS; you may not get control "at midnight EXACTLY"
Second, your Calendar object represents a time in the past (unless it happens to be midnight at the time you are executing that code, in which case it represents the present). Try a start time in the future.
Related
I want to start alarm when i have selecting the days,hours,and minutes.
This is my code so far :
public void startAt() {
Intent alarmIntent = new Intent(backgroundApplication.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(backgroundApplication.this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_WEEK,calendar.WEDNESDAY);
calendar.set(Calendar.HOUR_OF_DAY,7);
calendar.set(Calendar.MINUTE,35);
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 5, pendingIntent);
}
For the example i set the DAY_OF_WEEK is today(friday) it works great. But when i changed it into Wednesday, or other day before friday it still running.
Is there any other way to start in selected days ?
According to the documentation http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating%28int,%20long,%20long,%20android.app.PendingIntent%29, the 2nd parameter is the trigger time in milliseconds and if you set it to a time in the past, the alarm will trigger immediately. If you want the alarm to only start from next Wednesday, then you have to advance your Calendar time to the next Wednesday with calendar.add(Calendar.WEEK_OF_MONTH, 1). By the way, in your code, you don't need to have calendar.setTimeInMillis(System.currentTimeMillis()).Calendar.getInstance() will return the current time by default. You should also use static field Calendar.WEDNESDAY.
How to create a AlarmManger which can be invoke on fixed date and time, This can be also repeat continuous by nature
unfortunately any of the options on the AlarmManager for repeating tasks doesn't allow such a fine control. Your best approach is to on every alarm, you re-schedule it for the next month.
PendingIntent pendingIntent = // set here your action
Calendar calendar = // set this guy to be the next 5th day
AlarmManager am = // get reference to the manager
am.set(RTC, calendar.getTimeInMillis(), pendingIntent);
on inside this Pending intent action you repeat the code. For example, let's say you want to launch a BroadcastReceiver
onReceive(Context context, Intent intent){
Calendar calendar = // set this guy to be the next 5th day
AlarmManager am = // get reference to the manager
am.set(RTC, calendar.getTimeInMillis(), pendingIntent);
}
to set the calendar object is easy:
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY, 5);
I just read a good answer to do the same.
The code is-
Calendar cal=Calendar.getInstance();
cal.set(Calendar.MONTH,5);
cal.set(Calendar.YEAR,2012);
cal.set(Calendar.DAY_OF_MONTH,11);
cal.set(Calendar.HOUR_OF_DAY,16);
cal.set(Calendar.MINUTE,10);
cal.set(Calendar.SECOND,0);
Intent _myIntent = new Intent(getApplicationContext(), ReceiverClass.class);
PendingIntent _myPendingIntent = PendingIntent.
getBroadcast(getApplicationContext(), 123,
_myIntent, PendingIntent.FLAG_UPDATE_CURRENT| Intent.FILL_IN_DATA);
AlarmManager _myAlarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
//_myAlarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + (10 * 1000), _myPendingIntent);
_myAlarmManager.set(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), _myPendingIntent);
This is explained in android-alarm-setting-with-specific-date.
I want to set and cancel an Alarm for a particular time. I am doing the same using the TimePicker using the following code.
public void setRecurringAlarm(int randomTimer,long mills, int i){
Intent intent = new Intent(CreateAlarmActivity.this, AlarmReceiver.class);
intent.setData(Uri.parse("timer:" + i));
PendingIntent pendingIntent = PendingIntent.getBroadcast(CreateAlarmActivity.this, 1253, intent, PendingIntent.FLAG_CANCEL_CURRENT| Intent.FILL_IN_DATA);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,mills,
pendingIntent);
Toast.makeText(CreateAlarmActivity.this, "Alarm "+i+" isSet", Toast.LENGTH_LONG).show();
}
Note:-Suppose I set the alarm for 10:00 PM. It works fine for 10:00 PM. But when I again run the same code (after 10 PM) i.e once the time has been passed on which the alarm has been set and I recall that code (to reset the alarm), it starts running immediately. Why it is so ? I am unable to get where I am a wrong.
You can check if the alarm time is before the current time or not. If so, then set the alert time for the next day (if you want to fire alarm at least once, or want to set Repeating alarm).
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
if (System.currentTimeMillis() > cal.getTimeInMillis()) {
calendar.add(Calendar.DATE, 1);
}
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
public void scheduleAlarm() {
// time at which alarm will be scheduled here alarm is scheduled at 1
// day from current time,
// we fetch the current time in milliseconds and added 1 day time
// i.e. 24*60*60*1000= 86,400,000 milliseconds in a day
// Long time = new GregorianCalendar().getTimeInMillis()+24*60*60*1000;
Calendar cal = Calendar.getInstance();
cal.add(Calendar.HOUR_OF_DAY, 20);
cal.add(Calendar.MINUTE, 00);
cal.add(Calendar.SECOND, 00);
Intent intent = new Intent(CreateAlarmActivity.this, AlarmReceiver.class);
// create the object
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// set the alarm for particular time
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
PendingIntent.getBroadcast(this, 1, intentAlarm,
PendingIntent.FLAG_UPDATE_CURRENT));
Toast.makeText(this, "Alarm Scheduled ", Toast.LENGTH_LONG)
.show();
}
Hope this will help you
2 things:
If you are "recalling that code" by calling setRecurringAlarm(randomTimer, mills, i) using the same value for the mills parameter, then the time for the alarm will be in the past and it will trigger immediately (if you schedule an alarm with a trigger time in the past, the alarm triggers immediately).
Please remove | Intent.FILL_IN_DATA from the call to PendingIntent.getBroadcast(). It doesn't belong there as this parameter should contain only PendingIntent flags and it may do some damage.
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);
I'm creating an alarm application.
In my application, the user can select the days to fire the alarm, such as Sunday, Monday, so I used the Calendar class and AlarmManager to register multiple alarms.
If the selected day or days are less than the current day of the week, the alarm fires immediately.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, getDayint); //sunday = 1
calendar.set(calendar.HOUR_OF_DAY, gethour);
calendar.set(calendar.MINUTE, getmin);
calendar.set(calendar.SECOND, 0);
calendar.set(calendar.MILLISECOND, 0);
long TIM = calendar.getTimeInMillis();
Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, TIM, sender);
//repeat weekly
am.setRepeating(am.RTC,TIM, AlarmManager.INTERVAL_DAY*7, sender);
By using PendingIntent.FLAG_UPDATE_CURRENT you say that you like to have only one such alarm - so latest one wins - only one alarm weekly. And if TIM lies in past, alarm is fired immediately ( and then repeating ) So far - everything works as designed.
You may check whether TIM ( by the way, it is variable, and concention is that they shall be not uppercased like constants ) is less than System.currentTimeMillis() and add one week to it in this case