As the title implies, I'm looking to schedule a task to run on certain days at certain times. For example, I might have it run at 5:00 every Tuesday and Thursday. I've seen several scheduling methods for Android, but all of them seem to operate in the form of "do task after n delay" or "do task every n seconds".
Now I could probably jury-rig it by having it calculate the time to the next execution during the execution of the task itself, but that seems inelegant. Is there some better way to do this?
You've to set an Alarm to perform those tasks. Most probably you will end up calling a Service once the alarm is triggered:
private void setAlarmToCheckUpdates() {
Calendar calendar = Calendar.getInstance();
if (calendar.get(Calendar.HOUR_OF_DAY)<22){
calendar.set(Calendar.HOUR_OF_DAY, 22);
} else {
calendar.add(Calendar.DAY_OF_YEAR, 1);//tomorrow
calendar.set(Calendar.HOUR_OF_DAY, 22); //22.00
}
Intent myIntent = new Intent(this.getApplicationContext(), ReceiverCheckUpdates.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, myIntent,0);
AlarmManager alarmManager = (AlarmManager)this.getApplicationContext().getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
However, if you need to set specifically a day:
int weekday = calendar.get(Calendar.DAY_OF_WEEK);
if (weekday!=Calendar.THURSDAY){//if we're not in thursday
//we calculate how many days till thursday
//days = The limit of the week (its saturday) minus the actual day of the week, plus how many days till desired day (5: sunday, mon, tue, wed, thur). Modulus of it.
int days = (Calendar.SATURDAY - weekday + 5) % 7;
calendar.add(Calendar.DAY_OF_YEAR, days);
}
//now we just set hour to 22.00 and done.
Above code is a little bit tricky and mathematic. If you wan't something stupid aswell as easy:
//dayOfWeekToSet is a constant from the Calendar class
//c is the calendar instance
public static void SetToNextDayOfWeek(int dayOfWeekToSet, Calendar c){
int currentDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
//add 1 day to the current day until we get to the day we want
while(currentDayOfWeek != dayOfWeekToSet){
c.add(Calendar.DAY_OF_WEEK, 1);
currentDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
}
}
Related
I have an app that needs to set alarms for multiple days of the week, depending on what days the user sets them. I have it working where it triggers an alarm at the appropriate time, but am wanting to know how to do multiple without them overridding the current AlarmManager. For example, here is my test code:
final int alarmid = (int)System.currentTimeMillis(); //creates unique id for the alarm attached to the object
tempmainfrag.mainObjectList.returnSchedule(i).setAlarmId(alarmid);
for(int j = 0; j < 7; j++)
{
if(tempmainfrag.mainObjectList.returnSchedule(i).returnDays()[j]) //if this day of the week has an alarm
{
int adjustedday = j+2; //makes time for DAY_OF_WEEK where sunday = 1, monday = 2, etc.
if (adjustedday == 8)
adjustedday = 1;
Calendar startcal = Calendar.getInstance();
startcal.set(Calendar.DAY_OF_WEEK, adjustedday);
startcal.set(Calendar.HOUR_OF_DAY, tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[0]);
startcal.set(Calendar.MINUTE, tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1]);
startcal.set(Calendar.SECOND, 0);
Log.i("mydebug","Starting cal day of week: " + adjustedday);
Log.i("mydebug","Starting cal hour of day: " + tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[0]);
Log.i("mydebug","Starting minute: " + tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1]);
Intent intent = new Intent(this, SilenceHandler.class);
intent.putExtra("starttime",tempmainfrag.mainObjectList.returnSchedule(i));
intent.putExtra("alarm_message", "Test!"); //FOR TESTING
PendingIntent pendintent = PendingIntent.getBroadcast(this, alarmid, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmman = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmman.setRepeating(AlarmManager.RTC_WAKEUP, startcal.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, pendintent);
// startcal.set(Calendar.MINUTE, (tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1])+1);
// alarmman.setRepeating(AlarmManager.RTC_WAKEUP, startcal.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, pendintent);
}
}
The for loop iterates through days of the week, and at each iteration checks to see if the alarm should be set for that day. This code works (presumably), but to test if I could set another alarm on top of it I added in the last two lines of code that are commented out here. This makes the alarm go off a minute later, but not a minute earlier as well. I am doing this to demonstrate that if I want this code to work for multiple days of the week, the way the code is currently set up will just have the alarm set for the last day of the week that returns true. How can I make multiple alarms?
The problem is that although you are creating a unique ID for your PendingIntent, which would set separate alarms, in your test you are reusing the same PendingIntent, which would override your previous one. Create a new PendingIntent with a different alarmid to test this.
I am developing an application in which user would first be presented a simple UI with days and timings. user would select timings against each day. and click a button "Done". Now this would start alarm services to trigger on every day as per selected timings. (and will turn the bluetooth device off/on those timings). right now i am using separate service for each day (beginner's instinct). The application is working fine. Now what i want is that when the user click on the "Done" button, the application should keep running in background and when the user again click the application icon and click on the "Default" button, it should stop all the services. How can i achieve that ? Code for triggering service every sunday is as follows
time interval of 7 x days for the alarm to repeat every 7 days
long interval = 1000 * 60 * 60 * 24 * 7; // to make the alarm repeat at every 7 days
//getting values for hours, mins and AM/PM from the spinner boxes for sunday
index = sunHr.getSelectedItemPosition();
int sunHrInt = Integer.parseInt(hrList[index]);
index = spinnerSunMin.getSelectedItemPosition();
int sunMinInt = Integer.parseInt(minList[index]);
index = spinnerSunAmPm.getSelectedItemPosition();
//conversion of time to 24 hrs format
if (ampmList[index] == "AM") //(convert to 24 hr format)
{
if (sunHrInt == 12)
{
sunHrInt = 0;
}
else
{
if (sunHrInt != 12)
sunHrInt = sunHrInt + 12;
}
}
//setting current calender
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar
//setting calender for sunday
Calendar calSun = new GregorianCalendar();
calSun.add(Calendar.DAY_OF_YEAR, cur_cal.get(Calendar.DAY_OF_YEAR));
calSun.set(Calendar.HOUR_OF_DAY, sunHrInt);
calSun.set(Calendar.MINUTE,sunMinInt);
calSun.set(Calendar.SECOND, 0);
calSun.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND));
calSun.set(Calendar.DATE, cur_cal.get(Calendar.DATE));
calSun.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH));
//finding out when the sunday is to occur from today
days = 8 - calSun.get(Calendar.DAY_OF_WEEK); // how many days until Sunday
if (days >= 7)
{
days = days - 7;
}
calSun.add(Calendar.DATE, days);
//finally triggering the intent
Intent myIntentSun = new Intent(AndroidAlarmService.this, SunOffAlarmService.class);
pendingIntentSun = PendingIntent.getService(AndroidAlarmService.this, 0, myIntentSun, 0);
AlarmManager alarmManagerSun = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManagerSun.set(AlarmManager.RTC_WAKEUP, calSun.getTimeInMillis(), pendingIntentSun);
Use Preferences to store values and try it. it may help you
Hi guys this is what i have so far:
PendingIntent sender = PendingIntent.getBroadcast(mainactivity, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
showmsg();
the alarm comes after 10 seconds How can I make it in desire time i want, I have set a timepicker so how can i do it depending on the timepickers time to ring the alarm?
Thanx.
With your TimePicker, call picker.getCurrentHour() and picker.getCurrentMinute(). Use these values to calculate the total milliseconds of the given time of day (12:00 pm would equal 43200000 ms, for example) by multiplying by the milliseconds in an hour (3600000) or minute (60000). Then get the milliseconds of today's date when it started at 0:00. That would all look like this:
//time of day in ms
long totalTimePickerMs = (picker.getCurrentHour() * 3600000) + (picker.getCurrentMinute() * 60000);
//today's date in ms
Calendar c = Calendar.getInstance();
Date d = c.getTime();
long today = d.getDay() + d.getMonth() + d.getYear();
long total = today + totalTimePickerMs;
Essentially you are getting today at midnight (0:00) in milliseconds and adding to it the milliseconds of the specific time of day.
Then like you did before, except set the alarm with total as the second parameter.
I am using this code to create an Alarm in a activity that can be launched by the user.
The Alarm sends an intent that launches a broadcast reciever and then a service.
private void setGameAlerts(){
//Setting alarm to fire off NEW_GAME intent every 24 hours.
String alarm = Context.ALARM_SERVICE;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND,0);
calendar.set(Calendar.MILLISECOND, 0);
AlarmManager am = (AlarmManager)getActivity().getSystemService(alarm);
Intent intent = new Intent("NEW_ITEM");
PendingIntent sender = PendingIntent.getBroadcast(getActivity(), 0, intent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis() , AlarmManager.INTERVAL_DAY, sender);
Log.e("RELEASE LIST", "ALARM Set For 1 day from " + calendar.getTimeInMillis());
For some reason EVERYTIME the activity is launched it Automatically sends this intent and the service is launched. is there something wrong with my code that is causing this to happen other than the alarm going off everyday at 8 oclock?
It looks to me like you're setting it for 8am TODAY, not 8am tomorrow. For example, if I run this code:
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND,0);
calendar.set(Calendar.MILLISECOND, 0);
Log.i("Test", "Current time: " + System.currentTimeMillis() );
Log.i("Test", "Calendar time: " + calendar.getTimeInMillis() );
calendar.add(Calendar.DATE, 1);
Log.i("Test", "Calendar time with a day added: " + calendar.getTimeInMillis() );
I get the result:
10-06 23:26:50.050: INFO/Test(8890): Current time: 1317968810056
10-06 23:26:50.050: INFO/Test(8890): Calendar time: 1317913200000
10-06 23:26:50.050: INFO/Test(8890): Calendar time with a day added: 1317999600000
The calendar time is a number less than the current time, so therefore that calendar entry is in the past. It might make some sense that Android would immediately send the intent for an event that has past. If you add a day to it, or specify a date in your Calendar object, it should work.
Note that this numerical dates are simply the standard Unix time with milliseconds added on. If you drop the last three digits and put the number into a Unix time converter, you'll be able to check that the numbers you're working with make sense. Eg: use 1317999600 with the Unix time converter and you'll get 10am EST, which is 8am PST (my time zone).
I hope that helps!
In Android we set an alarm by setting the time until it goes off in milliseconds. Is there an easy way to find how many milliseconds there are until a certain time (hh:mm) or do I just have to calculate it mathematically?
Thanks!
Save your current time in milliseconds as
Calandar calendar = Calendar.getInstance();
Long currenttime = calendar.getTimeInMillis();
Long settime= <your set time in milliseconds>;
Here you can calculate the difference as follows:
Long differencetime = settime - currenttime;
int dif=(int)differencetime/1000;
Here you can set the time in calendar:
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + dif);
Here you can set the alarm for the settime.
AlarmManager alarmManager1 = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager1.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pi1);
Check out the first argument for AlarmManager.set(): With RTC/RTC_WAKEUP, you can specify a fixed time rather than an elapsed time.
That said, if you need to use the elapsed time, it's pretty trivial to calculate the number of milliseconds that need to elapse. Worst case, you could use the Calendar and/or Date classes.
Date now = new Date(), b = new Date(year, month, day, hour, min);
b.getTime() - a.getTime();
And here's another way to get the time in milliseconds to a certain time:
Calendar c = Calendar.getInstance();
c.set(c.YEAR, c.MONTH, c.DAY_OF_MONTH, 17, 1, 0); // 5:01 pm
long alarmTime = c.getTimeInMillis();
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmNotification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime, 1000 * 60 * 60 * 24, pendingIntent); // Millisec * Second * Minute * Hour // Same time every day
RTC_WAKEUP allows the alarm to still activate when the phone is asleep. Use RTC if you want to wait until the user wakes up the phone themself.
Use am.set() if you don't want the alarm to repeat
Let me know if this helps.