Android Work manager constraint change after work is started - android

Does the Work manager will stop the work after the constraints become not satisfied while the work is processing.
For example, work requires charger connected constraint, after connecting the charger the work starts, and then the charger gets disconnected, does the Work manager will stop the work, as it's not satisfying the constraints anymore

If a constraints is not satisfied anymore during the execution of a worker, WorkManager will signal its stoppage.
Keep in mind that stoppages are cooperative in WorkManager, so your Worker will need to implement the onStopped() callback and it can use the isStopped() method while executing long running loops/computation.
From the doc:
You should cooperatively abort any work you had in progress and release any resources your Worker is holding onto. For example, you should close open handles to databases and files at this point. There are two mechanisms at your disposal to understand when your Worker is stopping.
Alsoi from the doc:
Note: WorkManager ignores the Result set by a Worker that has received the onStop signal, because the Worker is already considered stopped.
If you are using CoroutineWorkers, these are going to handle stoppages automatically in the defined scope.
From WorkManager's threading guide:
CoroutineWorkers handle stoppages automatically by cancelling the coroutine and propagating the cancellation signals. You don't need to do anything special to handle work stoppages.

Related

Best way get GPS Location in background for Android API level 30 and higher

My application determines the speed limit by the user's location and tells the user if he has exceeded it.
Starting with Android API level 30 and higher, Google has defined IntentService as deprecated and suggests using WorkManager or JobIntentService and also states that it is necessary to migrate from Firebase JobDispatcher to WorkManager. I see two ways to solve this problem:
Start OneTimeWorkRequest and specify to restart this method periodically in this method while the application is running in the background.
Run PeriodicWorkRequest with a minimum allowed interval of 15 minutes. In this method, run the JobIntentService method, which runs for up to about 10 minutes, but the method may not run or may be destroyed by the system before it is complete.
I'm worried about:
potential memory leaks;
potential problems with WorkManager or JobIntentService when going from foreground to background and vice versa
the ability to use the MVVM pattern
I would prefer going with second option, it gives you more time between each rescheduling of the Worker.
Regarding your concerns:
Only possible leak is misconducting location callbacks. This can be easily tracked down, you shouldn't worry too much about it.
Scheduled Worker are put in the database and are executed independently of the application. Which means, user-visibility of the application has no effect. In your case, I presume you want to cancel your scheduled work once the user resumes the application, that being said you can assign a tag to the Worker and purge any scheduled or on-going once visible to the user.
I prefer to keep Workers isolated from the MVVM and just inject Use cases/interactors in the worker and do execute the use case/query the interactor. WorkerManager offers fine APIs to query the Worker status, you might need to write common ground between your previous implementation and for API >= 30. Treat the Worker as different execution container for your use case.

ReactiveX and Android Background Services

This is more of a conceptual question than a matter of programming.
I am currently using ReactiveX (RxJava + RxAndroid) to run an interval timer, as the other methods of timers are too inaccurate when it comes down to the milliseconds. From what I understand, ReactiveX requires several threads to operate correctly.
I need the timer to also be running in the background when the user is not on the app itself. But from reading the Services documentation, it seems that background services can only run on the main thread. I was wondering if it is still possible to run the ReactiveX timer in the background despite this limitation. Implementing services would require some major changes to my project, so I thought that I would try asking before doing so.
The project is written in Kotlin, but I doubt that matters. However, any insight on what this code would look like in Kotlin would be appreciated!
Even though the actual work is done in the background, it seems appropriate to use a foreground service, not a background service.
A background service can easily be stopped by the system or even be deferred to maintenance (time) windows.
In order to get a "foreground" for the service it is common to use a notification and bind to it:
https://developer.android.com/guide/components/services#Foreground
As to the other question: The life cycle functions of a Service like onStartCommand() might be called on the main thread but you'd be using RxJava to switch to another thread instantly and return from those functions.
Even after the lifecycle return, the service is considered "running" to the system. They just exist so get things going and should return promptly.
Workmanager is not necessarily a good choice here as it is designed for deferrable tasks. So you cannot be sure when it exactly will be started. Foreground service seems like the way to go here.

Still getting "Excessive network usage (background)" warning after running network code in Foreground service

By referring to Proper way to tackle and resolve "Excessive network usage (background)"
After few months of debugging, we are now able to run all network related code in Foreground service.
However, we are still getting "Excessive network usage (background)" warning in Android Vital.
When foreground service code is executed, a notification UI will always shown in status bar area.
When we "quit" our app, we launch the foreground service, using WorkManager. The WorkManager will return immediately, after foreground service is launched.
public class SyncWorker extends Worker {
#NonNull
#Override
public Result doWork() {
final Intent intent = new Intent(WeNoteApplication.instance(), SyncForegroundIntentService.class);
ContextCompat.startForegroundService(
WeNoteApplication.instance(),
intent
);
return Result.success();
}
}
public class SyncForegroundIntentService extends IntentService {
private static final String TAG = "com.yocto.wenote.sync.SyncIntentService";
public SyncForegroundIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
final Context context = WeNoteApplication.instance();
NotificationCompat.Builder builder = new NotificationCompat.Builder(...
startForeground(SYNC_FOREGROUND_INTENT_SERVICE_ID, builder.build());
// Perform networking operation within foreground service.
stopForeground(true);
Side note
We don't think we are sending a lot of data. As you can see our latest release, we fall in the lowest range (0 - 5 MB per hour)
Any idea why we're still getting "Excessive network usage (background)"? Apparently, we no longer perform any networking call in background.
We utilize https://developer.android.com/reference/android/app/Service.html#startForeground(int,%20android.app.Notification) and https://developer.android.com/reference/android/content/Context.html#startForegroundService(android.content.Intent)
You are using a Worker to invoke the ForegroundService. From the Worker's documentation:
Worker classes are instantiated at runtime by WorkManager and the
doWork() method is called on a pre-specified background thread (see
Configuration.getExecutor()). This method is for synchronous
processing of your work, meaning that once you return from that
method, the Worker is considered to be finished and will be destroyed. (...) In case the work is preempted for any reason, the same instance of Worker is not reused. This means that doWork() is called exactly once per Worker instance. A new Worker is created if a unit of work needs to be rerun.
A ForegroundService is a Service that you put in the foreground state, that means, the system will not kill the process if it needs CPU or if your app is closed. This and only that.
I wasn't able to find the documentation of Android Vital proving this, so this is only my suspicion, but I'm quite positive this is the case: this means that regardless of the fact that you use ForegroundService or not, Android Vital still counts this as background work.
A proper way to move your app’s mobile-network usage to the foreground is to call DownloadManager with proper visibility setting set (as stated in the link you have provided). Please let me know if that helps - if not we'll try something different. Btw, were you able to narrow down the statistics to a specific API version? (there were some background threading changes in 9.0 and 8.0 so this can also be a clue)
If you're doing this:
When we "quit" our app, we launch the foreground service, using WorkManager. The WorkManager will return immediately, after foreground service is launched.
then you're technically scheduling a worker probably with network constraints every time the user shuts the app.
From the documentation for "Excessive background network usage" link
When an app connects to the mobile network in the background, the app wakes up the CPU and turns on the radio. Doing so repeatedly can run down a device's battery
Thus, even though you're not sending the threshold data of 50MB/ 0.10% of Battery session you're getting this warning cause your app is technically waking up the CPU a lot in the background (for network pings).
Though i'm not sure if this is the problem or not, what you can do is, since even the worker documentation guide says:
WorkManager is intended for tasks that are deferrable—that is, not required to run immediately—and required to run reliably even if the app exits or the device restarts
you can try these:
Scheduling a foreground service as soon as the user shuts the app, instead of scheduling a worker, checking inside the onHandleIntent whether the user is online or not (having a connection and for devices above 7, a flowing internet connection as well).
You can try scheduling a worker to run periodically, lets say every few hours based on your business-side requirements, this could be problem if that's not how you wish to back-up the data, but it serves the real purpose of the worker being a deferred task and not something to be executed immediately.
Not sure about this, never tried, but theoretically looks valid, you can use a Unique Work with a mode called REPLACE to replace the worker and have an initial delay of lets say 30mins, this is a hack, but this will delay running of your worker for 30mins, and in the meanwhile if the user opens and shuts the app again, it will replace the old worker with a new one. This solution has its own drawbacks as well, like sometimes the task wont be scheduled if the user is using the app constantly. But will reduce the total number of times the worker had ran.
Finally, the architecture you're using is valid, the whole thing about using a FG service and a worker to schedule it, just that you're doing it quite often. Source

android service (Keep on running in background statement confused me )

I have some confusion with android service
As per the documentation
It will keep on running in the background on main thread . It doesn't run in a different thread.
My doubt is what is the meaning of keep on running in background . Will it execute the onStartCommand() again and again. I am really very confused with this line (Keep on running in background )
if it will not execute onStartCommand again and again then what is the benefit of Keep on running and if it executes onStartCommand again and again then it is using cpu more and more
Line which confused me is highlighted in the image please have a look
As already noted in a comment, for your particular purpose (monitoring a setting, here: volume), you can follow a non-polling approach which is described e.g. here: Is there a broadcast action for volume changes?
In general, on a modern (though not perfect) environment like Android, there's almost never a reason to actively poll something, because nobody could afford wasting so much resources, and also, you'll always risk to miss events, so you'd be tempted to poll more frequently -- this is a race which your implementation is always going to lose.
Once more, the following statements are plain wrong:
A Service runs on your app's main/UI thread. If you think this is the case then you need to read about the android:process attribute of the manifest's activity tag. Also. even if you do not let your service run in a separate process, the phrase a service runs on your app's main/UI thread suggests that your main/UI thread gets blocked by your service. Of course, hopefully nobody leaves iot art that; it's easy to just process the service's events on your app's main/UI thread and delegate the tasks to worker threads, which is what every sane implementation should do.
With START_STICKY, you can ensure that your service will always be running after it got started. Of course, this is naive and means that whoever claims this has not completely understood the meaning of this flag in conjunction with the description of the process lifecylce for Android Services. Quote: Note this means that most of the time your service is running, it may be killed by the system if it is under heavy memory pressure. If you read the section, you will know that Android is going to kill the process with your running service at any time without notice if it needs memory for another task with higher priority and your service is not related to an app which the user currently looks at. In other words, if the system is low on memory and the user opens a spreadsheet which requires most of the system's memory, then the background internet radio media player and all fancy stuff is likely to get killed, period.
A Service runs on the thread of your app and after started it keeps running until it calls finish() or android needs memory.
But the running doesn't necessary means that it is processing something. onStartCommand() is called only when someone calls startService() on your service.
So the service instead of running always it's always in memory ready to be run when needed. The main use of service is to do some processing that keeps running even if you change activities, like a music player that keeps playing when you are changing activity looking for the next music to play.
Edit: On Documentation "A Service is not a separate process....A Service is not a thread. It is not a means itself to do work off of the main thread".
A Service is "A facility for the application to tell the system about something it wants to be doing in the background"
"A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated."
Service Documentation

Android: AsyncTask vs Service

Why do I read in the answer to most questions here a lot about AsyncTask and Loaders but nothing about Services? Are Services just not known very well or are they deprecated or have some bad attributes or something? What are the differences?
(By the way, I know that there are other threads about it, but none really states clear differences that help a developer to easily decide if he is better off using the one or the other for an actual problem.)
In some cases it is possible to accomplish the same task with either an AsyncTask or a Service however usually one is better suited to a task than the other.
AsyncTasks are designed for once-off time-consuming tasks that cannot be run of the UI thread. A common example is fetching/processing data when a button is pressed.
Services are designed to be continually running in the background. In the example above of fetching data when a button is pressed, you could start a service, let it fetch the data, and then stop it, but this is inefficient. It is far faster to use an AsyncTask that will run once, return the data, and be done.
If you need to be continually doing something in the background, though, a Service is your best bet. Examples of this include playing music, continually checking for new data, etc.
Also, as Sherif already said, services do not necessarily run off of the UI thread.
For the most part, Services are for when you want to run code even when your application's Activity isn't open. AsyncTasks are designed to make executing code off of the UI thread incredibly simple.
Services are completely different: Services are not threads!
Your Activity binds to a service and the service contains some functions that when called, blocks the calling thread. Your service might be used to change temperature from Celsius to Degrees. Any activity that binds can get this service.
However AsyncTask is a Thread that does some work in the background and at the same time has the ability to report results back to the calling thread.
Just a thought: A service may have a AsyncTask object!
Service is one of the components of the Android framework, which does not require UI to execute, which mean even when the app is not actively used by the user, you can perform some operation with service. That doesn't mean service will run in a separate thread, but it runs in main thread and operation can be performed in a separate thread when needed.
Examples usages are playing music in background, syncing data with server in backgroud without user interaction etc
AsyncTask on other hand is used for UI blocking tasks to be performed on a separate thread. It is same like creating a new thread and doing the task when all the tasks of creating and maintaining the threads and send back result to main thread are taken care by the AsyncTask
Example usage are fetching data from server, CRUD operations on content resolver etc
Service and asynctasks are almost doing the same thing,almost.using service or a asynctask depends on what is your requirement is.
as a example if you want to load data to a listview from a server after hitting some button or changing screen you better go with a asynctask.it runs parallel with main ui thread (runs in background).for run asynctack activity or your app should on main UI thread.after exit from the app there is no asynctask.
But services are not like that, once you start a service it can run after you exit from the app, unless you are stop the service.like i said it depends on your requirement.if you want to keep checking data receiving or check network state continuously you better go with service.
happy coding.
In few cases, you can achieve same functionality using both. Unlike Async Task, service has it's own life cycle and inherits Context (Service is more robust than an Async Task). Service can run even if you have exited the app. If you want to do something even after app closing and also need the context variable, you will go for Service.
Example: If you want to play a music and you don't want to pause if user leaves the app, you will definitely go for Service.
Comparison of a local, in-process, base class Service✱ to an AsyncTask:
✱ (This answer does not address exported services, or any service that runs in a process different from that of the client, since the expected use cases differ substantially from those of an AsyncTask. Also, in the interest of brevity, the nature of certain specialized Service subclasses (e.g., IntentService, JobService) will be ignored here.)
Process Lifetime
A Service represents, to the OS, "an application's desire to perform a longer-running operation while not interacting with the user" [ref].
While you have a Service running, Android understands that you don't want your process to be killed. This is also true whenever you have an Activity onscreen, and it is especially true when you are running a foreground service. (When all your application components go away, Android thinks, "Oh, now is a good time to kill this app, so I can free up resources".)
Also, depending on the last return value from Service.onCreate(), Android can attempt to "revive" apps/services that were killed due to resource pressure [ref].
AsyncTasks don't do any of that. It doesn't matter how many background threads you have running, or how hard they are working: Android will not keep your app alive just because your app is using the CPU. It has to have some way of knowing that your app still has work to do; that's why Services are registered with the OS, and AsyncTasks aren't.
Multithreading
AsyncTasks are all about creating a background thread on which to do work, and then presenting the result of that work to the UI thread in a threadsafe manner.
Each new AsyncTask execution generally results in more concurrency (more threads), subject to the limitations of the AsyncTasks's thread-pool [ref].
Service methods, on the other hand, are always invoked on the UI thread [ref]. This applies to onCreate(), onStartCommand(), onDestroy(), onServiceConnected(), etc. So, in some sense, Services don't "run" in the background. Once they start up (onCreate()), they just kinda "sit" there -- until it's time to clean up, execute an onStartCommand(), etc.
In other words, adding additional Services does not result in more concurrency. Service methods are not a good place to do large amounts of work, because they run on the UI thread.
Of course, you can extend Service, add your own methods, and call them from any thread you want. But if you do that, the responsibility for thread safety lies with you -- not the framework.
If you want to add a background thread (or some other sort of worker) to your Service, you are free to do so. You could start a background thread/AsyncTask in Service.onCreate(), for example. But not all use cases require this. For example:
You may wish to keep a Service running so you can continue getting location updates in the "background" (meaning, without necessarily having any Activities onscreen).
Or, you may want to keep your app alive just so you can keep an "implicit" BroadcastReceiver registered on a long-term basis (after API 26, you can't always do this via the manifest, so you have to register at runtime instead [ref]).
Neither of these use cases require a great deal of CPU activity; they just require that the app not be killed.
As Workers
Services are not task-oriented. They are not set up to "perform a task" and "deliver a result", like AsyncTasks are. Services do not solve any thread-safety problems (notwithstanding the fact that all methods execute on a single thread). AsyncTasks, on the other hand, handle that complexity for you.
Note that AsyncTask is slated for deprecation. But that doesn't mean your should replace your AsyncTasks with Services! (If you have learned anything from this answer, that much should be clear.)
TL;DR
Services are mostly there to "exist". They are like an off-screen Activity, providing a reason for the app to stay alive, while other components take care of doing the "work". AsyncTasks do "work", but they will not, in and of themselves, keep a process alive.

Categories

Resources