Im trying to make a countdown timer run in the background of my activity, it needs to run constantly until it finishes, but not sure how to make it work with a service. I also need to update the display on my main activity
Uh, not all services run 100% of the time. Nothing is a battery drain unless it's executing at 100%. If you look at the actual battery consumption of an Android device, you'll see that the largest percentage comes from the screen. The next comes from radios. Running a process costs very little.
You can use an IntentService to fire off an alarm at regular intervals. The service can send intents to itself. Have one intent action to start the service, and one to turn off the alarm. Make a third action for resetting the alarm.
To start the service, send a "start" intent to the IntentService using startService(intent). This should trigger a method that creates an intent with action "cycle", puts the intent in a PendingIntent, and schedules a repeating alarm with AlarmManager.setRepeating().
After the interval that you set for the alarm, the AlarmManager will take the "cycle" intent out of the PendingIntent and send it back to your service. Your service should handle "cycle" by rebuilding the PendingIntent and restarting the alarm. This goes on indefinitely. You can put anything else you want to do when the alarm goes off in the handling for the "cycle" action.
When you want the alarm to stop, send the "stop" intent. In response, your service should cancel the alarm by reconstructing the PendingIntent and then calling AlarmManager.cancel().
Notes: The main entry point for an IntentService is onHandleIntent(). You call everything else from there. When that method finishes, the service goes inactive until it receives another intent. The only place you can "see" it is in cached processes. Once you stop the alarm, the system will eventually figure out that the service isn't being used, and garbage-collect it.
Services are the way to do background work. I suppose you can run some AsyncTask or a thread, but you still want to run them in a Service, otherwise you've linked them to something that's running in the foreground. If the task doesn't need to interact with the user, particularly if it can work asynchronously to your activity, then use a service.
Related
Pretty new to android, so forgive me if this is a dumb question...
So, I'm making an app with a countdown timer that will ring periodically, and then again when the countdown hits zero - simple enough. However, I want the app to keep running even when the user closes the application or the phone is asleep, so that whenever the timer rings, the app will wake up and display an activity showing the time until the countdown is finished. To do this, I'll need to use a service, and lo and behold, the google devs made the AlarmManager service just for me! Sweet!
However, I noticed 2 things:
1) the AlarmManager class has no default constructor, so I'm assuming I can't just extend it and tack some logic on so that I can get all this done in one shot. Ok, cool - I'll just make a service that instantiates AlarmManager at the start, and implement my logic there.
2) In the documentation, I don't see any way of getting either the elapsed time or the remaining time from AlarmManager once it is running.
So, my question is: does this mean that I will need two timers that I start at the same time? Say, an AlarmManager to wake the phone up and call the activity, and a CountDownTimer contained in the service to hold the remaining time and call the alarm ringtone?
Thanks for helping out my clueless ass.
You could extend AlarmManager. However the common way is to get an instance of it, which is running as a system service.
Get the instance using Context.getSystemService(Context.ALARM_SERVICE) and you will be able to register your PendingIntent to that system service, which is independent to your own app. The PendingIntent can either start an activity or send broadcast with some Intent. You don't monitor the elapsed time constantly in AlarmManager. Rather, you calculate the time difference between the current time of your method call, and the desired time to fire your event. And then you set an alarm in AlarmManager with a PendingIntent representing the action you wish to take at that interval, or a time point.
On the other hand, if you want maximum flexibility, run your service as foreground service and listen for system broadcast like ACTION_TIME_TICK, which is fired every minute. Alternatively if you don't run service in foreground you could also run your service with START_STICKY, which guarantees that your service will be restarted after the system kills it (due to sleep or closing app). Think this as a background service that is constantly running. This provides you a lot of flexibility in your implementation.
I am making an app that needs to execute a function each hour even the app is closed.
First of all, I thought to create a service, but during my tests, I realise that android sometimes kills my service. So I was looking for another solution and I found AlarmManager. I have implemented it and it seems to work but I have the doubt if it will happen the same the service or it will run forever? (Until reboot of the mobile...)
Another question, it is necessary to create a new thread to execute the process in alarm manager or it runs directly in other thread?
I have implemented it and it seems to work but I have the doubt if it will happen the same the service or it will run forever? (Until reboot of the mobile...)
It will run until:
the device is rebooted, as you noted, or
the user uninstalls your app, or
you cancel the events yourself, or
the user goes into Settings, finds your app in the list of installed apps, taps on that entry, and clicks the Force Stop button
It's possible that alarms will need to be scheduled again after your app is upgraded (I forget...).
it is necessary to create a new thread to execute the process in alarm manager or it runs directly in other thread??
Unless the work you are going to do will take only a couple of milliseconds, you will want a background thread for it. That leads to two possible patterns:
If you are not using a _WAKEUP-style alarm, use a getService() PendingIntent to send control to an IntentService every hour
If you are using a _WAKEUP-style alarm, you will need to use a getBroadcast() PendingIntent, and have it either invoke your subclass of my WakefulIntentService, or you will need to manage a WakeLock yourself to keep the device awake while you do your bit of work
No, Android won't kill scheduled alarms and they got executed as planned unless app is replaced or device is rebooted. Use broadcast receivers for these events to reschedule Alarms. There's no way to prevent Force Stop as it kills all of your app components and threads totally.
That depends on what Alarm Manager do. If it sends a broadcast, the receiver limit is 10 second.
If it starts an Activity, Service or Intent Service, there is no limit. For Activity and Services you must finish or stop it and for Intent Services until the process is finished. Be aware that you can't have another thread inside Intent Service and you'r limited to code inside the OnHandleIntent.
Also you must consider device state. If it's sleep and you are using Wake Up flag receivers won't need a wake lock, but others do. It won't take long for device to go back to sleep.
Don't waste system resources with a service because Alarm Manager do what you want.
I have two examples of Intentservice. One is the Download example in the commonsware book. the other is at http://www.vogella.com/articles/AndroidServices/article.html#servicecommunication_handler.
Both of these examples show the service executing a finite task and they both apparently destroy themselves by running to the end of the scope of the onHandleIntent event.
The service I am writing has to have events and listen for things. One is a LocationListener listening for GPS movement. Another makes Posts to a REST service and listens for replys. I want it to run until a time has elapsed or until it was told to quit by the activity that started it.
How do I keep it running? Where, for instance, do I put my implementation of LocationListener?
Thanks, Gary
How do I keep it running?
You don't. IntentService is designed to do a piece of work (or perhaps a few off a queue, if commands happen to come in rapidly), then shut down.
The service I am writing has to have events and listen for things.
Then you should not be using an IntentService. Use a regular Service, with your own background thread(s) as needed.
To keep a service running, your service need to return START_STICKY in the service method onStartCommand().
With this, the service will be running even if you exit form your activity.
Note:
The Android still kills services after some time (30 mintus to 1 hour) if they are not foreground services. Use startForeground(notification) to make it foreground.
good luck
You can achieve this in either of two ways,
AlarmManager
TimerTask
AlarmManager is android's in-buite class that allows you to execute certain action on particular time peroid.
TimerTask does same thing as AlarmManager, you can repeat certain action of your code again and again.
However AlarmManager is ligher in the execution so i suggest you to go with AlarmManager class.
Create an AlarmManager that fetches the GPS Co-ordinates and post them to server on regular interval basis.
Have a look at to this AlarmManager Example.
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).
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).