I have to call a service in every day on a particular time.obviously i had choose AlarmManager for waking up my service.and all working well other than AlarmManager triggering immediately when i set the past time.but it's working fine when i set time after current time.
For better clarification i will say an example.
WORKING ATTEMPT : Current time is 09.00 AM am setting schedule as
10.00 AM.And AlarmManager doing his job perfectly.
FAILURE ATTEMPT :Current time is 10.00 AM am setting schedule as
09.00 AM.And AlarmManager calls the services immediately.
Actually i need to invoke my service tomorrow 09.00 AM as the scheduled time is past.
I referred some query almost matching this one but it wasn't good enough.What i am doing wrong ?
My Code
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY,10);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
myIntent.putExtra(ACTION, ACTION_SC_1);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, REQUEST_CODE_SC_1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
Dont use alarm manager use GcmNetworkManager which was introduced in the last IO. It will work like a charm and you will have the ability to set in to inexact alarm so u wont need to wakeup the device. From the google IO site : Google Play Services has added the GCM Network Manager which functions mostly like JobScheduler, but extends to prior releases before Lollipop.
From the documentation
Like set(int, long, PendingIntent), except you can also supply a period at which the alarm will automatically repeat. This alarm continues repeating until explicitly removed with cancel(PendingIntent). If the stated trigger time is 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.
It is working intentionally like this.
As Bonatti said above, this is documented behaviour of the API when you set a time in the past.
You will need logic in your app to push out the alarm by 24hrs if it is already past 10am at the time when you want to set the alarm.
The easiest way to do this is probably to use the Calendar object as you have, then query
if (calendar.after(SystemClock.currentTimeMillis()) {
// Push alarm out til tomorrow.
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
If you need the alarm to be triggered at 9AM sharp, don't use setRepeating() as it will not launch at the exact time since Android KitKat (this is also documented, you should really read the docs).
Use Calendar to build the timestamp from your desired alarm time. Check if the result timestamp is smaller than the current timestamp System.currentTimeMillis(), in that case it's in the past so add 24 hours to it to schedule it for the next day.
Finally, use AlarmManager.set() on older versions or AlarmManager.setExact() on newer versions of Android to schedule your alarm. Once the alarm goes off, you can schedule the next one using the same technique.
Related
in order to save battery I'd like to switch off all connections (bluetooth, wifi, mobile network) and other power-consuming features at a given time (say 11 pm).
What is the best way to do this? I am thinking of a service that is started after booting so I do not have to restart the service manually. For the beginning I even don't need an app for the UI - I can hardcode the time for switching off. Maybe later it would be nice to be able to change the time via GUI but this is not really necessary.
So the only time the service needs to do something is at my desired time, however in order to detect the time it needs to run continously in the background without consuming too much energy.
What is the best way for this kind of job?
I guess this is what you're looking for:
https://developer.android.com/reference/android/app/AlarmManager.html
You can send a repeating alarm that will trigger a service on a specific time of the day to do (or any actions you want). Please refer below for setting the time on a specific time:
Intent myIntent = new Intent(AndroidAlarmService.this, KillNetworkService.class);
pendingIntent = PendingIntent.getService(AndroidAlarmService.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 23); //23 for 11pm
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
for my example, it will start the KillNetworkService.class everyday at 11pm, and from that service, you can now turn off your network.
Reference for alarm manager tutorial:
http://android-er.blogspot.com/2010/10/simple-example-of-alarm-service-using.html
This is strange, what is the reason method setInexactRepeating trigger approximately at given time rather then exact time.
I need to trigger alarm on every day basis at one particular time, i have said
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
// Set the alarm's trigger time to 8:30 a.m.
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
I have set time 8:30 am in the calendar, when i shift device day to next day, alarm get trigger immediately even before i shift device time to 8:30am.
What is happening here, why i can't make exact trigger using this api, if any of you have experience this, could you share your experience. Thanks!
According to documentation (here) there is text:
As described above, choosing the alarm type is often the first step in
creating an alarm. A further distinction is how precise you need your
alarm to be. For most apps, setInexactRepeating() is the right choice.
When you use this method, Android synchronizes multiple inexact
repeating alarms and fires them at the same time. This reduces the
drain on the battery.
For the rare app that has rigid time requirements—for example, the
alarm needs to fire precisely at 8:30 a.m., and every hour on the hour
thereafter—use setRepeating(). But you should avoid using exact alarms
if possible.
With setInexactRepeating(), you can't specify a custom interval the
way you can with setRepeating(). You have to use one of the interval
constants, such as INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY, and so on.
I hope it could help You bit. There is also small example for it in previous link I gave You.
I'm scheduling repeating alarms in order to execute service one a period of time.
// Set the alarm to start at approximately 24:05 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 24);
calendar.set(Calendar.MINUTE, 5);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, );
Some question about the implementation :
What happens if user delete the application (including the service), will something crash on the next alarm ?
Again if user delete the application, the alarms will continue running ? If so, how can I cancel any repeating alarms ?
Where/When is the best place/time to initiate the repeating alarms ? Should I wrap it with "only once" block ?
I'm not completely sure but I can give answers for your questions;
1- If user deletes your application and service, I think anything crash on the next alarm because I think your application is running on the service. (if there is no service, alarm does not works i think)
2- If user deletes your app, alarm will works but if service doesn't works, alarm does not works.
3- I think there is some options for repeating alarms and user can select one of this options.
I would like to make a delay(10 min) for user then after it, user can edit something.
to do this,I created a setAlarm function :
public void setAlarm(Context context,int user,int time) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, sef_time.class);
intent.putExtra(ONE_TIME, Boolean.FALSE);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
am.set(AlarmManager.RTC, 1000*60*time , pi);
}
everything works fine, but my alarm manager has a delay.
for example:
setAlarm(.....,int 10);
It has a delay : 00:10:03 second or 00:10:10 second 00:10:20 second !
where is my wrong ?
As you can see here:
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.
With the new batching policy, delivery ordering guarantees are not as
strong as they were previously. If the application sets multiple
alarms, it is possible that these alarms' actual delivery ordering may
not match the order of their requested delivery times. If your
application has strong ordering requirements there are other APIs that
you can use to get the necessary behavior; see setWindow(int, long,
long, PendingIntent) and setExact(int, long, PendingIntent).
Applications whose targetSdkVersion is before API 19 will continue to
get the previous alarm behavior: all of their scheduled alarms will be
treated as exact.
If it's very important that the alarm be exact, use setExact (When the device's SDK is 19 or above).
The easiest way to make system have a delay and then sound an alarm at the exact specified time is using setExact(), and the code can be something like this.
am.setExact(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + (time_you_want_to_delay_in_milliseconds) ,pi);
I have an alarm that works fine if i am interacting(using) with my application but it dose not works if I set it for next day and not interacting with my app.Therefore I am getting doubt is this because my application process is not running at that time.
here is what I am doing
Calendar calSet = Calendar.getInstance();
calSet.set(Calendar.HOUR_OF_DAY, selectedhour);
calSet.set(Calendar.MINUTE, selectedminute);
calSet.set(Calendar.YEAR, year);
calSet.set(Calendar.MONTH, monthOfYear);
calSet.set(Calendar.DATE, dayOfMonth);
alarm = new Intent(ActivityA.this, Service.class);
pendingIntent = PendingIntent.getService(getApplicationContext(), i++,alarm, 1);
alarmanager.set(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),pendingIntent);
From AlarmManager
AlarmManager provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running. Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted.
In simple way, it will work until your device has been rebooted.
You can read Android AlarmManager after reboot where #CommonsWare has been given a link of his sample application which persists Alarm even after device reboot.
Please ignore below section, it seems not valid. I will remove in future
You can read more about application kill at How to create a persistent AlarmManager, and How to save Alarm after app killing? can give you the idea about how to handle such issue (to persist alarm if application has been killed).
Yes it worked but proper understanding see doc.
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
see here http://developer.android.com/reference/android/app/AlarmManager.html
Looking at the AlarmManager documentation..
http://developer.android.com/reference/android/app/AlarmManager.html
I don't see anywhere where it states that killing your app will remove all alarms that have been scheduled by that app. More specifically it states if your app is not started, it will start it for you.
I have done my own testing and can validate this by..
Setting an alarm 5 sec in the future.
Then closing app from recents.
Then watching logs for my broadcast to be received.
Keeping in mind this was done with a signed apk.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MILLISECOND, 5000);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
I would also keep in mind what Pankaj Kumar said about the restarting alarms on boot. That is the one place you need to cover yourself, because AlarmManager does clear all alarms on device restart.
We need to enable our app in autostart manager in app manager, some handsets like Vivo v5,
In Vivo v5, we can find out this menu in
iManager > App Manager > Auto Start Manager > Enable our app here.
Then your alarm / alarm manager will trigger alarm if the app is killed or closed.