I have used background service in for updating tasks like playing with web server frequent times(sending Geo-Location data or send/get web data time-wise) in my android apps and also I have faced many problems(slow process, application hang) for this.
But In my current application I have used the AlarmManager followed by PendingIntents for some tasks which worked well.
So I think its good if I replace each updating tasks which use service with AlarmManager followed by PendingIntents.
Is it the right way or I am going doing a big mistake ?
All kind of suggestions are appreciable.
Thanks in advance.
Services and alarms scheduled with AlarmManager serve different but complementary purposes at times. When you schedule an alarm with one of the set methods, the alarm will be triggered at the specified time and you should handle it on a BroadcastReceiver. This means that your handling has to be responsive and cannot have asynchronous operations. According to the docs:
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active. (...) Anything that requires asynchronous operation is not
available, because you will need to return from the function to handle
the asynchronous operation, but at that point the BroadcastReceiver is
no longer active and thus the system is free to kill its process
before the asynchronous operation completes.
In case you want to handle more complex operations, it is advised to start a service for doing so. Even if you use the more recently available goAsync() call on the receiver, you are still expected to be responsive:
This does not change the expectation of being relatively responsive to the broadcast (finishing it within 10s)
So it ultimately depends on what you are trying to achieve, when to use each of these or combine their use.
I don't tell that using Alaram Manager is a big mistake..
Right now to run the background services there are only few options upon which the easy and partially reliable one would be AlarmManager.
Though sometimes the Alarm Manager is not 100% reliable on looking into other categories for doing these operations (like Asynchronous Thread and delay looping techniques) are much more complex and not that much reliable to do the background services.
When we compare the pros and cons of the techniques needed for background services AlarmManager wins the race.
I prefer AlarmManager would be the good option for these kind of background services upon thinking the options open right now to complete the tasks in background.
Hope that Google will comeup with a better solution to handle the background services.
Related
I have a foreground service and while it's active I want to run some events based on specific exact time that you a user previously set, it can be one time or it can repetitive every day for example.
I don't want to use AlarmManager because it triggers system events and you need some permissions for it, I have a running service anyway so why would I use something like this... So it should lifescoped to the service
I don't want to use Handler and its func postDelayed or launch and delay of Coroutines because it's like inventing a wheel, especially when you need to implement logic for repeatable events for a specific time.
So I'm looking something as local broadcast messages but with time configuration like in alarm and I could use set date/time instead of millis delay logic
I might need some more clarifying details to give better advice, but the following should give you an idea of the possible options and their pros and cons.
As much as AlarmManager might seem like a pain, it is probably your best bet for something like this, especially if the events are spread out over a longer period as the question hints (e.g. once a day). The alternative would be to use something like Handler, Coroutines, or a TimerTask inside the service. In addition to introducing the complexities of managing repeating events (as you mentioned), all of these require that the service is constantly running and presumably doing nothing other than waiting to fire an event, which is wasteful and likely not precise over a long period of time. Further, the service could be killed by the system and then you'd have to recreate all the timing logic, whereas AlarmManager scheduling is more persistent.
If your foreground service really is active doing other things for the entire duration in which you want these events to fire, or if the requirement is that the events fire if and only if the service is already active, then these options could be back on the table, but I'm not sure without more information.
If exactness is not an issue, you could potentially use OneTimeWorkRequest or PeriodicWorkRequest; see this documentation.
If your main concern with AlarmManager is using date/time scheduling instead of milliseconds, that shouldn't be an issue as most temporal classes provide easy ways to convert to milliseconds.
Overall, because of the inherit difficulty of precise scheduling, a system-based implementation like AlarmManager is best if exactness is the goal, and other options will incur an unnecessary waste of resources.
According to https://github.com/ReactiveX/RxAndroid/issues/257#issuecomment-164263215 . interval is just for active code, and if app is not wake up, it will not work. So how to use interval for background scheduling tasks?
Please DO NOT use this solution:
To use interval from RxJava you'll have to make sure your app's process stays alive. One way to do it is to put use the Observable in a foreground service. This is a bad idea because the service is NOT actively delivering value to the user. Waiting for time to pass is not delivering value for the user. Again please DO NOT use this.
AlarmManager and JobScheduler (or it's backport GcmNetworkManager) are far better choices for repeating background activities. If you use AlarmManager.setInexactRepeating() the system can batch jobs from multiple apps together to save battery. Using JobScheduler enables you to execute your background jobs in specific conditions, eg. when the device is connected to the internet or when battery is more than 20%. (Internet is required to check the weather).
interval from RxJava does have it's usage on Android. It's an excellent replacement for Runnable.postDelayed for relatively short durations. It makes the code shorter and more readable.
If you need to schedule a task that should be run even if app is not active anymore then use AlarmManager.
If you need to schedule a task that should be run only when app is active then you can use Observable.interval() and react on emission to execute some code and please don't forget to unsubscribe from the Observable when appropriate (when Activity is paused, etc) so app won't burn the battery!
I need to implement a background task that needs to update the UI about every 10 seconds. I tried the following approaches, but most of them failed.
1) AlarmManager
I started an intent service via AlarmManager. It seems that AlarmManager is only suitable for very low frequencies, like several hours. If I set it to 10 seconds, then the UI does not respond anymore. Why is that? Doesn't the intent service run in a separate thread?
2) IntentService with infinite loop and Thread.sleep
App was terminated after about 30 seconds, UI was not responding at all. Is intent service only for very short background tasks? I found contradicting information about this. Why is the UI not responding although intent service should run in a separate thread?
3) AsyncTask
When using AsyncTask, the UI remains responsive. But for some reasons, no other AsyncTask is started from the UI. I heard about some limits of concurrend AsyncTasks, but 2 should not be too much?
4) Own Threads
That worked. Background service and UI are fully functional. However, I read that it is bad practise to use threads directly when updating the UI. What would be the best way in this context to send data to the Activity?
What do you recommend for a background task that needs to update the UI and reoccures about every 10 seconds?
Best regards!
Since you need the task to happen in recurring fashion, i would think Alarm Manager is better option.
These are my reasons.
It allows you to fire Intents at set times and/or intervals.
We can use them in conjunction with broadcast receivers to start services and perform other operations even when your app is not running, and even if the device itself is asleep.
They help you to minimize your app's resource requirements. You can schedule operations without relying on timers or continuously running background services.
As per android documentation,
For timing operations that are guaranteed to occur during the lifetime
of your application, instead consider using the Handler class in
conjunction with Timer and Thread. This approach gives Android better
control over system resources.
What would be the best way to implement this. I have an Android app that will use my python server to allow communication between 2 phones in rounds. Rounds mean that they can't talk to each other until a round start and once they send a message they can't send another until the other person responds which will then start a new round.
I was thinking I would use the IntentService but it seems wrong to have the server constantly starting and stopping and I don't won't to have to worry about the issues with asynctask or is that the best way to handle it. How could I have a service that should receive and send messages to the client, seems services are more one way things?
Intent services are nothing more that worker threads that are triggered by intents, execute their actions in a separate thread and then get shut down. They are designed to be started and stopped.
If you need to perform stuff like an http get, or in any case interaction that do not require to stay connected to the server, use intent services and get your activities notified using broadcast events.
If your app needs to stay connected with the server (i.e. permanent tcp connection), the way I'd go for is to have a service (not an intent one) that performs the networking stuff using an asynctask or a more classic thread hosted in the service. You can then make the activity interact with the service using bindToService() .
I'd recommend not to use asynctasks inside an activity. You will risk to loose the server response in case of horizontal / vertical view changes, as oneilse14 stated in his reply.
I highly recommend the IntentService/Broadcast Receiver route. Avoiding the nasty configuration change issues associated with AsyncTask will make your life ten times easier.
As far as i understood your problem is of type worker-queue model Producer-consumer model). Intentservices are meant to do that. You should use services if and only you need to do multithreading. You do can communicate with Activity and Service by using IBinder interface.
Asynctask are just a specialized threads so that you can update your UI easily. But for your case IntentService seems to be best option.
I would use an Alarm, which is scheduled via the AlarmManager, as then it can be set to check if the round has started/turn. It has the advantages of a service but not the horrors of battery drain. It takes a frequency to how often the Alarm should run, which even includes enumerations of time (e.g. 1 hour/day/week).
When the Alarm runs it could poll to see what the current state is and react accordingly. For example a notification could go into the status bar and phone could make an audible noise and vibrate.The benefit of this is that the user does not have to keep the app running as the Alarm will trigger a broadcast receiver.
An example of the Alarm code: http://www.androidcompetencycenter.com/2009/02/android-basics-alarm-service/
I'm implementing an background process that will update information my app uses.
I only want this process to update say once a day, if the process gets data newer than what it had before I want to present the user with a notification, exactly like twitter/gmail does.
I want the update process to run automatically, even when the main app is not open.
Is a Service the best way to go? I've been reading quite a bit about this, I figured a service running all the time for something that is only going to do work once a day seems a little overkill.
However I notice google run service for friendlocation and google+ services continuously on my nexus.
I've look into starting my service via the AlarmManager so its only started when required.
Some posts also suggest using the Handler class, I don't think this will work.
Just looking for the best practice here.
I figured a service running all the time for something that is only going to do work once a day seems a little overkill.
Absolutely.
I've look into starting my service via the AlarmManager so its only started when required.
This is the correct answer.
If you only want your code to be invoked if the device is on, implement an IntentService, do your work in its onHandleIntent(), and have AlarmManager start up the service on your desired schedule.
If you want your code to force the phone to wake up, you can do that, but you will need to use a _WAKEUP-style alarm, and you will probably want to look at my WakefulIntentService, designed to handle this pattern.