I have an application which is supposed to retrieve data from a Website every x minutes. Something like a push service is not possible. After retrieving the data a notification should appeare at the info bar or what ever you call it. I was reading and reading and at first I thought I should do a new thread which contains a localservice. Than I found out about the AlarmManager and thought "woa" that should be even better since the AlarmManager is also using some kind of wake-up in order to run a given Intent while sleeping. So my final decision is to use an alarm which starts a service which is doing the data collection and notification every x minutes.
The questions I have are:
Is this really the best way to do it.
Does AlarmManager automatically start the service in a new thread? If not how do I do this. (Just create a new thread in which I initialize the alarm?)
You are confused about how to do it. You need all that things together.
AlarmManager fires the intent which starts the service(via BroadcastReceiver). Service creates new thread, inside which you can fetch data.
At this situation AlarmManager seems to be a right way to do this.
From AlarmManager you need to create the server/thread to perform desire task.
Related
I'm developing a little Android app, that needs to run a background process, used to start a remote connection periodically (for example, to check if there is new data on the server). This process obviously needs to work also if the application activity is not running at the moment.
As I can see in documentation, there are two types of approach to develop a scheduled background process in Android, working also when the application is closed.
Services
Alarms
The first one is not so good for my requirementes, because it can be killed by OS in case of low memory, so it is useless for me. startForeground() is not so good because I want the process is silent.
Alarm is ok, because it can't be killed by the OS, so it can work indefinitely. But... If I schedule an Intent with the AlarmManager, how can I preserve a reference to the Intent, surviving at application restart?
For example, if I want to cancel, or reschedule the Alarm, I need the reference to the initial Intent to cancel it thorugh the "AlarmManager.cancel(Intent i)" method. But if the application was restarted by the user, how can I obtain a reference to the initial Intent that was used to start the alarm?
Is there another way to stop an alarm if the launching application was restarted?
about alarms, you can cancel using the intent characteristics, so you don't need a reference to the original intent. In any case, the alarms mechanism still need you to run something on a service.
In any case, you missed another possible solution: SyncAdapter. Its purpose is to sync with servers, but you can do whatever you wish in the code, and it's unlikely the OS will kill it, as opposed to the other solutions you've mentioned.
Sadly even now it lacks on documentation and samples, but I think it can fulfill your needs. Here's what I've found
yes, note that cancel is looking for a PendingIntent, not an Intent per se.
so
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, R.string.some_string, new Intent(this, InitialIntent.class), 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
gets you where you want to be.
note that I'm not getString'ing that string, that's becasue I want a unique Id/request code for this intent that I'm not going to screw up copypasting; I reference the same number when creating the alarm in InititalIntent.
This question was just answered, here:
How can I get the context of other activity?
Just cancel the intent you scheduled
Your best bet would be to make use to push notification (via GCM), whenever something new is available on the server. I am working on similar application where data can be pushed from one side (producers) and needs to be pushed to the consumer apps.
You need to look at BroadcastReceiver and GCM specific communication model. Hope this helps
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.
My application shows content for a site that also has a notification system. I want to show if there are new notifications, and I am using an AlarmManager that calls an IntentService.
My question is: where should I start/register this AlarmManager? I've put it in the onCreate() of my activity just for proof-of-concept (and its working fine, thank you very much :) ), but if you would start that activity twice, you would get multiple alarms.
The only possible solution I've come up with is this, but I don't know if this would be best practice
Start the manager in an onCreate() if the preference "alarm started" is false
Set some variable that it is started in preferences.
Now if the alarm stops for some reason, there's no way to restart it. So, a variation would be:
Always call cancel in the onCreate()
And then always set the Alarm.
This seems like a common pattern: Wanting to periodically get information with an alarm, and not setting that alarm more then once. How should I do this? When, where and how to register the alarm?
Also, continueing on #Zelimir 's comment: can you check if a certain alarm is allready set?
Ideally, the alarm would be set regardless of the activity being started or not of course, but that might be another thing.
For completeness, this is the code I'm currently using to start the alarm:
AlarmManager alMan = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(this, CommentService.class);
PendingIntent penInt = PendingIntent.getService(this, 0, i, 0);
alMan.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES,
penInt);
For even more completeness, the app description / situation.
The app is basically showing blogs (journals if you will) from a certain page. It has activities for adding entry, viewing entries, adding comments, etc. On the 'mother' site there is an option to recieve notifications (like the number you see here on SO too when you get a message). I want to show if there are new messages, and so retrieve them every xx minutes. It would be shown in the notificationbar for now, but it might feed some sort of widget later.
If you need more info: the app is called Androblip and it supports a site called blipfoto.com
When, where and how to register the alarm?
That is impossible to answer in the abstract. It depends entirely upon what the business rules are for your app, which you declined to supply in your question.
If the monitoring is to be happening all the time, a typical pattern is to register the alarm:
in onCreate() of your main activity for the very first run of your app
in a BOOT_COMPLETED BroadcastReceiver, to handle reboots, which wipe the AlarmManager roster
can you check if a certain alarm is allready set?
No, but you can cancel it without issue. Just create an equivalent PendingIntent and call cancel() on the AlarmManager.
I am creating an app which needs to retrieve a textfile from a webserver.
I have the manual retrieving done, just that I am thinking of adding a service to make the service check for the textfile like every 5 minutes and then send a notification to the user when a textfile is detected.
Is it ok to use a service here or do I have to use other methods?
Because the service will be kept running.
The best way of doing this is setting a repeating alarm using AlarmManager, a PendingIntent and a BroadcastReceiver as well as a Service. That way you don't have the service running all the time.
So the AlarmManager fires off the PendingIntent which is then picked up by the BroadcastReceiver which then starts your Service to perform the task in the background using a Thread or AsyncTask etc. Also look at IntentService which runs a Looper to process an Intent and then shuts itself down.
This is a great use of a service. Just make sure to allow the user to enable or disable service component. Also, try to shut it down when its not necessary (when the user cannot react to it).
I am writing an app which needs to periodically check the server for new messages and notify the user. I have seen some examples using AlarmManager to hit a BroadcastReciever which seems like the right thing to do, but i cant seem to get it to work.
Can anyone show me a step by step tutorial for this sort of thing (repeating alarm which triggers some kind of background code that fires a Notification)?
TIA
Here is one complete example: http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/
The pattern this example uses, and one that I've found that seems to work well, is to use a boot receiver to setup the AlarmManager (and of course also check to start the polling from your main Activity too, for the case when your app is installed and the system is not booted) and have the AlarmManager send an Intent for another receiver: http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealBootReceiver.java
And then from the AlarmReceiver start an IntentService:
http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealAlarmReceiver.java
From your IntentService then make your network call to poll for data, or whatever you need to do. IntentService automatically puts your work in a background thread, it's very handy:
http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealService.java
Check the docs for these classes too, a lot of into in there.
The caveat with this example is that it does not deal with the wake lock gap (the excellent CommonsWare code does that if you need it), but it may give you some more ideas about how to potentially address the "poll using AlarmManager and Service" stuff.
UPDATE: the code is now here: https://github.com/charlieCollins/android-in-practice