I want to show notification at certain time and day by using retrofit2 networking.
But in alarm manager doc. It mentioned that isn't proper fpr networkong job. But in workmanager doc it says for the exact time job use alarm manager. What would be better for me to use? Alarm manager nor work manager
Android has introduced so many things that need to save battery life like:
Doze version 1 - API 6.0
Doze version 2 - API 7.0
https://developer.android.com/about/versions/nougat/android-7.0-changes#perf
Removing CONNECTIVITY_CHANGE Manifest declaration and others in - API 7.0
https://developer.android.com/guide/components/broadcasts
Background execution limitations in API 8.0
https://developer.android.com/about/versions/oreo/background#services
App Standby Buckets API 9.0 (Upgraded in Android 12)
https://developer.android.com/about/versions/pie/power#buckets
https://developer.android.com/about/versions/12/behavior-changes-all#restrictive-app-standby-bucket
https://developer.android.com/topic/performance/appstandby
Battery Saver improvements in API 9.0
https://developer.android.com/about/versions/pie/power#battery-saver
https://developer.android.com/topic/performance/power/power-details
App Hibernation in 11 and 12 API.
All this stuff were not done for us to be able to do whatever we want by using the WorkManager. WorkManager was created to integrate all this requirements in a single API.
That is why the idea behind it is:
do some work
finish it at some point for sure(even if the device is restarted)
SAVE THE BATTERY AND NETWORK USAGE BY COMPLYING WITH THE ABOVE
Before that you had the AlarmManager to wake up in exact time
Services to keep the app process alive by giving your application priority. You still have them with the exclusion that now the starting services in the background are problematic. As per:
https://developer.android.com/about/versions/oreo/background#services
So if you want to do things like this you need to fully understand the Android API and limitations.
If you need help in StackOverflow - you need to fully understand your use case, you should have really put your mind into trying to understand it, communicate all these limitations with your PMs and explain to them that the Android Ecosystem is pretty complicated, there are a lot more applications besides the one you are writing and they all compete for resources. We can't do everything that we want. It is highly unlikely for the user itself to want to do long-running operations in exact timing starting from the background. But it might need it. Also, you have the option to ask to be exempted from battery optimization:
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
Also, some people try to use Push notifications, but it is highly unlikely that it will work in your case. You can send high-priority ones, but if android detects that the user is not interacting with the notification they will lose its priority. And if you do not have the priority and also want to do a long-running operation - you need to create... a Work in the WorkManager :)
But long story short:
what will wake you up:
AlarmManager is exact
WorkManager is not
what will keep you alive:
Service
WorkManager(it uses its own service)
Related
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'm in the process of developing an app which would mainly just be doing background work to read data from a nearby BLE (Bluetooth Low Energy) sensor every 15 minutes (if Bluetooth is not switched on, it'll need to prompt the user to switch it on from the background service) and sync the data into the server once a day. I'm not sure of which approach would be most suited to do the background work as I need to have guaranteed timely execution of the background tasks as that's very critical to the purpose of the app.
I've looked at the following approaches:
Using a ServiceIntent instant with a WakefulBroadcastReceiver. But I found out that WakefulBroadcastReceiver has been deprecated and there has been more restrictions to run background work since Android O.
AlarmManager
JobScheduler
WorkManager (seems to be a good candidate but it's still in alpha and It doesn't seem to be production ready)
Any help will be much appreciated.
Thanks
My suggestion is to use WorkManager even in alpha. I am alredy use it for similar task and it works. First time i started to use it, there where crashes, but after new version become released no more crashes occurs. Google provide a good support to its library, so use WorkManager since its the best option for background tasks execution.
In my current application for a company Im having a ForegroundService that is running while the workers are on duty (logged in to the app).
It is important to keep that foreground service running while users are logged in. To recover from cases where this foreground service gets killed somehow (User task swipe accidently or System kill) ive implemented a periodic JOB with Jobscheduler which reactivates the ForegroundService in case it gets shut down. This technique works well pre Android 8 OREO. START_STICKY and other techniques alone did not do the trick for me.
In Android 8, as soon as the foreground service gets killed, the periodic job gets killed as well. Im getting the notification in logcat that the job is not allowed to run. To my understanding, Jobs schould be able to run even when app is in background or killed. And its working on pre OREO devices the way it should.
To my knowledge, I can fix that by enable the option "autostart" in app settings. But since there is no way to know if employees tunred that on, its not a reliable thing as well.
So my questions:
- Why does the Job scheduler stops working as it should in Android 8?
- Are there any other reliable techniques I could use to let my ForegroundService recover from shutdowns in ANDROID OREO?
Ive read https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c but that did not answer my questions
Thank you very much
did you try to put
.setPersisted(true)
Note: Requires the RECEIVE_BOOT_COMPLETED permission.
you can also see this question.
Job Scheduler not running on Android N
reading some references:
1- The services in andreo oreo if posses a buggle oreo will kill it for energy loss in 7 is a warning but in 8 applies more strict
2 - The jobs scheduler has a time of 15 minutes and avaces is not executed in the precise time debit that they look for the precise moment to execute the event without that the battery of the cellular one is descaste
I recommend that you use this library that provides evernote that is very good and very specific:
https://github.com/evernote/android-job
I have a use-case where, whenever a transaction is completed or failed, I have to wait in background(not going to freeze the UI) for 5 minutes and call a piece of code without user intervention. So AFAIK I need to implement Background Service for this.
I want to know which would be better for my scenario.
Workermanager ( JetPack )
Jobscheduler ( for API 14 - 21, Firebase JobDispatcher)
IntentService
And in Oreo and above, if I run background service will it show in the notification that the App is running in the background?
Now the recommended way to do background processing would be Jetpack WorkManager API. I will cite official documentation for the reasons:
WorkManager chooses the appropriate way to run your task based on such factors as the device API level and the app state. If WorkManager executes one of your tasks while the app is running, WorkManager can run your task in a new thread in your app's process. If your app is not running, WorkManager chooses an appropriate way to schedule a background task--depending on the device API level and included dependencies, WorkManager might use JobScheduler, Firebase JobDispatcher, or AlarmManager. You don't need to write device logic to figure out what capabilities the device has and choose an appropriate API; instead, you can just hand your task off to WorkManager and let it choose the best option.
In addition, WorkManager provides several advanced features. For example, you can set up a chain of tasks; when one task finishes, WorkManager queues up the next task in the chain. You can also check a task's state and its return values by observing its LiveData; this can be useful if you want to show UI indicating your task's status.
So instead of worrying every time which background processing to choose (as every task has it's recommended and appropriate way), you can simply use WorkManager and it will do it's job.
This is considering the following gotcha:
WorkManager is intended for tasks that require a guarantee that the system will run them even if the app exits, like uploading app data to a server. It is not intended for in-process background work that can safely be terminated if the app process goes away; for situations like that, we recommend using ThreadPools.
P.S. As WorkManager API is using JobScheduler, Firebase JobDistpacher or AlarmManager under the hood, you must consider minimum API levels for used functionality. JobScheduler requires minimum API 21, Firebase JobDispatcher requires minimum API 14 and Google Play Services.
For the full documentation check: https://developer.android.com/topic/libraries/architecture/workmanager
For your second question: as far as I know you will always see that notification, as it is notifying user that your app is consuming battery. The notification may be disabled by the user from settings in Android Oreo 8.1.
Going forward, the official android documentation suggests that you use a JobScheduler in place of a background service.
In many cases, apps that previously registered for an implicit broadcast can get similar functionality by using a JobScheduler job. For example, a social photo app might need to perform cleanup on its data from time to time, and prefer to do this when the device is connected to a charger. Previously, the app registered a receiver for ACTION_POWER_CONNECTED in its manifest; when the app received that broadcast, it would check whether cleanup was necessary. To migrate to Android 8.0 or higher, the app removes that receiver from its manifest. Instead, the app schedules a cleanup job that runs when the device is idle and charging.
https://developer.android.com/about/versions/oreo/background#services
WorkManager is probably (eventually) the solution you are looking for. It acts as an abstraction, deciding whether to use JobScheduler (if it's available) Firebase JobDispatcher (if it's available) or falling back to a default implementation otherwise. This way, you get the best of all worlds. It's still in alpha, however, so you may want to at least consider other options.
If you choose not to use WorkManager, a combination of JobScheduler and JobDispatcher is probably appropriate (see here).
However, if you target devices without Google Play Services below API 22, you will need to use another solution. In that case AlarmManager may be what you are looking for, since you need a delayed task with guaranteed execution. Using an IntentService for this is possible, but not as easy. It involves introducing a delay mechanism of some kind, of which there are several choices.
Note that since you are using a batching mechanism if you use one of the Job APIs or WorkManager, you will not see a notification in Oreo. AlarmManager/IntentService based solutions may show a notification, but likely not for very long, since the tasks are fairly short. This is especially true for AlarmManager.