Scheduling background work in Android - android

I'm new to Android so I want to make sure that the following solution is the correct one.
The problem:
I want to sync the device's local database with a database on my server, via a webservice, every 10 minutes. I already have a web service call that I can make that returns the new/updated records. What I'm wondering is what is the best way to schedule this task. I want the databases to sync even when the application is not running.
My solution (is this the correct route to go?):
I will have one BroadcastReceiver that listens for android.intent.action.BOOT_COMPLETED, in it's onReceive I will create an AlarmManager that sends a message to MyReceiver (via a PendingIntent) every 10 minutes. Also, in my application's startup I will do the same (create an alarm to send messages to the MyReceiver via a PendingIntent) - Since both alarms are sending messages to MyReceiver and their corresponding PendingIntents are initialized with PendingIntent.FLAG_UPDATE_CURRENT will the new alarm override the old one? (this is what I want to do, in case for some reason the alarm gets cancelled after device boot it should be restarted when the application starts).
In MyReceiver's onReceive() I will create a MyIntentService (this instance will make the webservice call and update the local database).
Is this a good solution? Any suggestions?
Thanks

Solution is fine...Actually all the AlarmManager instances get cleared when device turned off and rebooted.
The simple way is that...
First create AlarmManager when application started.
Second in onReceive of BOOT_COMPLETED BroadcastReceiver.
Its enough, PendingIntent.FLAG_UPDATE_CURRENT will make sure of having only one activated alarm at a time.
In this way, alarm registered when your application started. There will be no issue if its already registered via BOOT_COMPLETED. Activated alarm will deactivated when you turn off your device, but BroadcastReceiver to BOOT_COMPLETED will take care of registration new alarm at next boot.
If you decide that this answers your question, please mark it as "accepted". This will raise both your and my reputation score.
Also you need to review your interval to use network, it might be very resource consuming for device and user. One policy might be to have longer period of interval and check for update when user starts your app (this might not be user friendly but can save many system resources and battery power as well). Try to find some better policy according to your needs.

Using FLAG_UPDATE_CURRENT in that manner will override the existing PendingIntent if one exists. I'm not positive but I believe that as soon as you get into onReceive, the PendingIntent is consumed so it's no longer there to be overridden. In either case, it sounds like this is the functionality you are looking for and yes it's a good way to solve this kind of problem. My only other suggestion would be if the 10 minute interval timing is not absolutely critical then use one of the INTERVAL_ schedules (INTERVAL_FIFTEEN_MINUTES for example) in your AlarmManager to help conserve battery life; basically it lets allows all apps that run on intervals to "batch" their work together and wake the device up less frequently.

Related

Android AlarmManager Rescheduling Logic

I have an app which allows users to schedule alarms to sound at certain times, repeating at intervals of their choosing. I am using JSON to persist the alarm details, using SharedPreferences as storage.
I am using AlarmManager to schedule when my app should be notified that an alarm should sound to notify the user. I am currently using the setRepeating() method of AlarmManager, supplying the interval provided by the user. This works well, and in theory the app would never need to update the JSon which stores the next alarm time, as AlarmManager will just reschedule the next alarm time using the interval.
However, my thinking is that when the device is rebooted, I will need to supply a up to date alarm time to AlarmManager to avoid AlarmManager thinking an alarm has been missed as this is not necessarily the case.
So, what's the best way to do this?
update the JSon next alarm time when the alarm is sounded, even though this may not be necessary (setRepeating() handles this as long as there is no reboot)?
register for and listen for shutdown broadcasts and update JSon then (this raises questions - just how long will the app get to calculate and write alarm details to storage given that the phone is shutting down)?
don't update the JSon but add logic to the object which is woken by the AlarmManager to decide if the alarm just broadcast is valid and the user should be alerted?
I'm sure any of the above will work, but I can't decide which is the nicest way to do it.
This seems mostly a matter of choice. The problem you note parallels a general problem seen in Linux laptops and solved by anachrond. In my opinion, I would simply update the time and store it in SharedPreferences every time the event is received. Trying to listen for when the system shuts down might not be entirely reliable (what happens when your users -- probably drunk college students -- drop their device and the battery flies out?). Instead, I believe the best thing to do in this scenario would be to -- each time the alarm fires -- recalculate the time to send the next one, store it somewhere, and upon boot schedule appropriately.

Service or BroadcastReceiver?

First time I have tried to implement either of these and I am unsure which to use.
I want my application to create a time frame, e.g. 2/3/12 to 7/3/12. Multiple time frames such as this can be created. A different intervals (e.g. every 4 hours) I would like my application to preform some actions for each time frame. This needs to be done in the background.
I have first tried to implement this with a Service, but am having performing all the actions for each of the time frames concurrently. After reading the android blog "Multitasking the android way" I think that perhaps BroadcastReceivers are better.
Please advise
Please see my answer about using the AlarmManager - Running task periodicaly(once a day/once a week)
If you are only running a process at a set time rather than constantly (e.g. monitoring audio levels) then you are going to ask a service to sit there 90% of the time and do nothing except waste battery power. The AlarmManager solves this problem as it notifies the broadcast receiver to execute at the given times.
Edit: Also bear in mind that after phone restart all alarms are removed so you will need to register a broadcast receiver to be notified of the device boot-up so you can re-register any Alarms that are needed.
You should probably be using the AlarmManager and a IntentService.
The AlarmManager will kick of your IntentService at specified intervals. You can kick off the IntentService for each set of actions.

Android, Is it poosible to use system timer as broadcast receiver?

In my application I need to refresh my data in each 5s or 10s or 1 minute, according to my user preference.
I can create thread and use timer class but i want to know is there any other way? for example timer of system sends flag (broadcast something) and i get it in application (in order to refresh my data)?
Thanks
If you want to refresh the data every serval seconds, you can setup a Hanlder to do this. However, this requires your activity keeps running.
If you want to do something at a specific time, like an Alarm. You can use the AlarmManager. This would lauch your activity or other components even it is not running now.
If you just want to moniter the change in the system time. Well, there is a Intent ACTION_TIME_TICK . You can register a BroadcastReceiver to listent to it and implement your own code when the systemt brocasts it. However, the "TICK" interval is "One Minute" only and can not be changed.
AlarmManager is what you are looking for. It can be used to set up periodic events that are delivered via a PendingIntent (which can be turned into an Intent broadcast).
I would be wary checking for new data on such a regular interval unless the device is always connected to a power source, especially if you are making the check over a network. With that small a poll interval going to the nework the battery will be flat in hours.

Clarification of AlarmManager behavior in Android

I see all the examples of AlarmManager being set by an Activity.
My question is this:
If my application sets a recurring AlarmManager, does that persist even after the application that started is is closed and removed from memory?
If not, how do I start an AlarmManager at a lower level that is started by Android at boot up and if it ever fails or dies or throws an exception is restarted without the user having to do anything?
Lastly, if the action I wish for the BroadcastReceiver to undertake has no visual components, do I still have to create a separate Activity for it? In my case I want there to be a background uploader that wakes up and looks into a folder and if it sees files in that folder, sends them off to the server. I don't need any feedback to the user.
So, my ideal would be to have a magical, OS based AlarmManager that calls an IntentService which just handles the uploading, but I'm unclear on how to get such an AlarmManager running in the first place.
TIA
Yes, AFAIK the alarms "survive" and keeps getting triggered, even after the activity that registered them ends. But they don't survive a phone reboot.
If I understands your problem correctly, I think you can achieve what your looking for by creating a project with a broadcast receiver that listens for android.intent.action.BOOT_COMPLETED intents and then (re-)register a repeating alarm, which in turns starts a (Intent)Service to do the uploading.
You don't need an activity, but you probably would want one anyway, to let the user temporarily disable the upload mechanism by checking off a checkbox, or something. It would probably also be nice to let the user choose the frequency of your alarm, i.e. how often the service should be started and look for new files to upload. This would also be a good place to register your alarm for the first time.
I agree with Nicolai that you'd have 2 broadcast receivers in your application :
one that re-register the alarm on boot
one that starts your service when triggered by the alarm
You could still have an activity but it shouldn't be started by the alarm receiver (hence the service) : instead, maybe launch a notification as you start your service, with the user having the possibility to launch the activity from the expanded message of the notification.
maybe also think about setInexactRepeating (instead of setRepeating) for your alarm, as well as using a worker thread to handle the long uploads (in case the user wants to use your activity in the main thread at the same time).

How can I ensure a service is started at 9am and stopped 9pm every day?

I have a service that will monitor location changes daily. What I know so far that to start a service at boot, I have to follow the linked tutorial. This way I can get the service started at boot, but to save battery I need it only between 9am-9pm.
Question is pretty simple, so I will repeat:
How can I ensure a service is started at 9am and stopped 9pm every day?
Use AlarmManager to set two alarms, each with a PendingIntent that will call startService() on your service, but with distinct action strings ('start', 'stop'). When onStart() of your service detects the 'stop' action Intent, it arranges for an orderly shutdown (e.g., stopSelf()).
This will fail if the user applies a task manager to you in Android 2.1 or earlier, since the technique they tend to use will wipe out your alarms (in addition to killing the service). In that case, the user is presumably voting for your service to not run, so you should try to accommodate the user's wishes.
CommonsWare is right. This is the best way.
You are writing an application and you had better not to change anything out of the application. If you want to add a system service(on boot started service), you need to modify the BSP and add your service to systemserver.java. It's not recommended.CommonsWare's suggestion can do this work.
As you said about the activity, you can start the activicy when you receive the boot broadcast. Then do what your want.....

Categories

Resources