I need to do some computations every 15 minutes no matter if the app is in the foreground or in the background.
Firstly, I have implemented a more complex Background Services with a Pending Intent, Receivers and an Alarm Manager that triggers a function every 15 minutes. However, I realised I could achieve the same results by using a simple Timer.
I am programming in C# Xamarin.
I am just wondering which version would be more efficient and which one consumes the least of battery power?
thanks
AlarmManager is a sufficient solution. It is the traditional solution for doing work on a period basis. However the caveat is that people misuse it and it impacts the battery heavily. There are other problems with it, but I will not discuss that here.
I would recommend using JobScheduler for more efficient background work. The JobScheduler will handle wakefulness via it's own implemented WakeLock and provide us an API that we can specify certain criteria to control what we need to fulfill our tasks (Network, etc). If it cannot meet our criteria, we will have a callback that we can then figure out how to match it.
https://developer.android.com/reference/android/app/job/JobScheduler.html
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.
I am using a ScheduledThreadPoolExecutor in my application where I need consistent, precise timing with a delay of 2 seconds.
When would AlarmManager be preferred and from the API docs, it seems like it'd be more power efficient. Is one "meant" more to be used as a background processor or foreground? Would there be any hardware limitations, ie. If I use AlarmManager, would I be able to access the camera for instance as long as I requested that permission? Or, is that resource out of scope in this context?
JobScheduler is out of the question for me because that appears to require a 15 minute interval at a minimum.
Handler only appears to function when the app is in the foreground.
Are those my only options?
Let's say I want to build an app which requests current location periodically (e.g., every 10 minutes, this number should be configurable) and submits to a server.
I'm aware that Foreground Service and WorkManager are normally suggested for this kind of scenario. However which is would suit more? Below are my thoughts and doubts.
WorkManager - is mainly for deferrable background work whose execution is guaranteed. However I know that from Android 8 (API 26) background location was introduced and that restrict location to be updated only a few times every hour https://developer.android.com/about/versions/oreo/background-location-limits. Thus this perhaps doesn't meet the periodical updates as per the requirement.
ForegroundService - is perfect for something that runs and needs to make users aware of. It's recommended for this kinda scenario (location tracking) for privacy purpose. Google also creates a sample app to promote this practice https://github.com/android/location-samples/tree/master/LocationUpdatesForegroundService.
From the above analysis, it seems ForegroundService is the one. However I also found that WorkManager has a built-in support to use Worker in conjunction with ForegroundService via androidx.work.impl.foreground.SystemForegroundService https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running#long-running-kotlin
That makes me confused as to what should I use and what Google really recommend for this specific scenario.
Anyone has any idea?
If you want to communicate somehow with the service then use foreground service and if you want to have some processed input based on something else you did in that work manager then choose work manager.
Work manager doesn't have option to redeliver intents and all other commands like start sticky etc...
Since work manager is more suitable for syncing data with db, processing a file etc..
If you were to ask me, I'd choose foreground service since you can add a type location to the xml tag when you register it in the manifest.
Both of these solutions don't survive OEMs aggressive battery restrictions since WorkManager's work can be deferred and if I want instant execution combined with wake locks I can easily do it in the foreground service since it also has a binder option that works well for UI sync.
I am recording output from a accelerometer.
Can anyone recommend a reliable way to monitor onSensorChanged after the app has been closed (running the app in the background).
WorkManager
I have experimented with WorkManager. WorkManager appears to run only when the app is open. I read that this may be device specific as some devices force stop the app on close or otherwise prevent background tasks from executing once the app is closed.
sticky-notifications
I am curious about using sticky-notifications, although this would not be my first choice. I am now researching this option. I have noticed a few apps which implement this option. The downside is the sticky-notification can be viewed as annoying and the user may disable sticky-notifications.
Other options?
You should use a service if you want to run in the background. But probably the Android won't allow it because keep listening to a sensor in the background will consume too much battery. Mainly on Android P that is more rigorous with battery consumption.
WorkManager is not the right solution in this case as a Worker has an execution limit of 10 minutes, then it's stopped by the OS. But, time limit aside, WorkManager has been developed for other use case, so using for something like this (using some hack to reschedule a worker when you're close to the 10 minutes limit) seems a fight against the library design. To have an introduction behind the use cases that WorkManager is designed to solve you can take a look at this blog: Introducing WorkManager.
A Foreground service is an option, but I'm afraid that continuously monitoring the sensor can have a very bad impact on the battery life of the device. For more information on the available options, to run code in the background, your can check this blog: Modern background execution in Android
An alternative, depending on what you need to do with the sensor data, is to use the Activity Recognition API:
You can tell the API how to deliver results by using a PendingIntent, which removes the need to have a service constantly running in the background for activity detection purposes. Your app receives the corresponding Intents from the API, extracts the detected activities, and decides if it should take an action.
March 2021 Update
There have been a couple of updates since I originally wrote this answer:
WorkManager v2.3.0 introduced support for longer Workers with the option to "promote" them to Foreground Services using setForeground() for CoroutineWorkers and ['setGoregroundAsync()][5] for all kind of Worker`s. This is allows to overcome the 10 minutes limit and is documented in Support for long-running workers.
Android 12 is planning to introduce some changes to Foreground Services and this has some impact on WorkManager. The new v2.7.0, currently in alpha, is adding the concept of expedite work to provide support for Android 12 in a backward compatible way.
Overall, I still think that having your app monitoring the sensors while in background is going to have a bad impact on the battery of the device and you should look for alternatives.
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.