What performance gains Job Scheduler gives over startService() - android

From Oreo, a service will not work if the app is not in foreground, but we can use JobSchedular to perform background operations.
Then what's really is the difference between JobScheduler and startService(), and why android is supporting JobSchedular over startService() for background operations from oreo.
I can still Schedule tons of Jobs from backround, and it will also effect battery performance.

From Oreo, a service will not work if the app is not in foreground
Yes, it will. It merely needs to be a foreground service.
Then what's really is the difference between JobScheduler and startService()
startService() is immediate. A job scheduled with JobScheduler is not. JobScheduler can postpone the work until a later time, when other work needs to be done, to minimize the amount of time that power is consumed (for CPU, for WiFi, for mobile data, etc.).
Also, startService() always happens. A job scheduled with JobScheduler might not. You can put criteria on the job (e.g., requires a network connection), and the job will only be run if the criteria are met.
and why android is supporting JobSchedular over startService() for background operations from oreo.
Power consumption, mostly, as far as I can tell.
I can still Schedule tons of Jobs from backround, and it will also effect battery performance.
Yes, but Google has a much better API for being able to control that in the future. If developers abuse JobScheduler, future versions of Android can further rate-limit jobs, expand Doze mode for jobs, and so on.

From Android developers website:
The framework will be intelligent about when it executes jobs, and
attempt to batch and defer them as much as possible. Typically if you
don't specify a deadline on a job, it can be run at any moment
depending on the current state of the JobScheduler's internal queue.
While a job is running, the system holds a wakelock on behalf of your
app. For this reason, you do not need to take any action to guarantee
that the device stays awake for the duration of the job.
When you start a background service it is running even if the app is in the background, thus it uses resources. With JobScheduler the resources are only allocated and used for a particular job, and are freed when it's done.

Related

Difference between Foreground Service and JobScheduler

I have an app where I use a foreground service to start a number N of threads that sleep most of the time and sometimes wake up to do some measurements.
I used foreground services because I need that these measurements must be done at specific and exact time without background limitations introduced by Android 8.0.
This seems to work and from documentation seems that there are no problem, but I read also about JobScheduler.
There is an advantage to use Jobs to schedule work at specific accurate time or my solution can be used without problems.
First a fact
In JobScheduler, the System execute your Job(Task) in application's JobService
and the JobService class also extend the same Service class that we use to define Foreground Service. So by using the both, we can execute code in background
Now the main difference is, Foreground Service is always running(by showing notification to user) and consuming the battery and memory of the user even, if your threads are sleeping and no code is executing.
As it's running always you can do whatever you want precisely at any moment of time. maybe it's good for your app's point of view but it's bad for user. your app draining the battery unnecessarily and consuming the RAM.
To address this problem we got JobScheduler. you can Schedule a job to be executed based on some criteria. Your app will only wake when the criteria is met, but it's not precise.it depends on many factors like doze mode etc.
you can look more about that here
The conclusion is
If your task is not needed to be execute at exact time then you should use JobScheduler (recently WorkManager is better as it use JobScheduler internally and more advance) to save your user's battery
and according official document
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.
For your use case, you will be better off using a WorkManager which according to the android documentation, uses JobScheduler on API 23+ and a combination of BroadcastManager and AlarmManager on API 14 - 22.
With a WorkManager your jobs will run reliably even if your app exits or the device restarts.
https://developer.android.com/topic/libraries/architecture/workmanager

Perform critical un-deferrable work in a system application service

I am working with a system application. It has to perform some extremely critical tasks in a service that are triggered by broadcasts from the system.
Due to the background execution limits introduced in Oreo, I've been thinking a lot about how to perform the tasks in the background.
The tasks have the following requirements:
They may not be deferred, they have to be started instantly.
They shall be started even if the phone is idle (or dozing, I haven't really understood the difference)
They are highly critical. They shall complete after being started, under all circumstances.
I looked into using IntentService. But, they recommend using JobIntentService instead due to the background execution restrictions. However, this doesn't comply with my requirement of not deferring the work. It also says that JobScheduler does not run during doze. When running on O or later, JobIntentService will perform the task as a JobService Job:
When running as a Job, it will be subject to standard JobScheduler policies for a Job with a setOverrideDeadline(long) of 0: the job will not run while the device is dozing, it may get delayed more than a service if the device is under strong memory pressure with lots of demand to run jobs.
It seems like using a regular IntentService may expose the tasks to the possibility to be stopped/killed by the system under certain circumstances, imposed by the new restrictions from Oreo and above.
The safest option seems to be to launch a foreground service. But, I don't necessarily want to show a notification during the service's lifetime. Also, I believe that if the user accidentally disables the notification channel in the settings, the service cannot be started anymore. I'm also worried about edge cases where the system may arbitrarily kill or stop my service, or simply stop my work in some other way by not honoring my wake lock etc.
I recently came across the android:persistent in the application tag in the manifest. It says it can only be used by system applications. According to this blog post from 2011 setting this attribute to true renders your application and it's services un-killable. It also implies that it can let you have a background service that is "always alive". But how does this relate to doze, battery optimizations etc? Do I still have to acquire a wake lock and whitelist my app from battery optimizations in order to continue performing the background work during doze conditions?
Thanks a lot for reading and I hope you have some valuable input. I am currently a bit confused, trying to put all the pieces together. It doesn't help that the documentation is (as per usual)... lacking.

IntentService + startForeground vs JobIntentService

Since Android Oreo background execution limits, the docs recommend to refactor IntentServices to JobIntentService.
https://developer.android.com/about/versions/oreo/background
JobIntentService runs immediately as an IntentService below Oreo, but schedules a Job on Oreo+
https://developer.android.com/reference/android/support/v4/app/JobIntentService
In what cases would it make sense to run a normal IntentService as a foreground Service with a persistent notification, and when is a JobIntentService better?
One downside I can see in JobIntentService is that it doesn't start immediately.
Foreground service is not affected by Doze, but you still have to use wake locks, if you need your task to be continued when the screen is off.
The JobIntentService (which uses the JobScheduler) manages wake locks for you, but you have less control when the job will be started.
I would use the foreground IntentService (or Service) for high priority tasks (e.g. downloading a database) that should run immediatelly and that should not be paused / killed by system.
I would use the JobIntentService in conjunction with AlarmManager to schedule low priority tasks like refreshing the widget's data periodically.
If you want to make long running operation something like Music Player use Foreground Service with notification. because JobIntentService has time execution limit like JobScheduler. ( 10 minutes)
If you think that user don't need to know about your work you can use JobIntentService without notification.
You don't need to worry about Doze mode if user is actively using your app.
There are some cases for Doze mode, according to https://www.bignerdranch.com/blog/diving-into-doze-mode-for-developers/
Light-Doze starts to kick in shortly after both the screen is off and
the device is not charging, waiting only a couple minutes before
applying the restrictions just to make sure the user has stopped using
their phone
For example, user turned screen off while you are computing something. Your task is finished and you want to run background service. In that case your JobIntentService can be deffered, because device can be in doze mode.
However, if you want immediately perform background operation use ForegrounService with WakeLock, because ForegroundService is not working when the screen is off.

Alarm Manager vs Job Scheduler vs ScheduledThreadPoolExecutor

this question is just to get some ideas on these concepts to see what people in the industry use these for.
If you can just give a few example uses for each of these, I would greatly appreciate it. I know how they work and did read the google documentation on them but I still seem to be having a hard time picking one over the other. I don't need you to explain to me how they work. I am simply asking for a few of their example uses. How you ended up incorporating them into your apps and why you picked them over the others.
Thanks
AlarmManager
Using the AlarmManager to Schedule Tasks at the System Level
The AlarmManager provides access to system-level alarm services. Using the AlarmManager allows an application to schedule tasks that may need to run or repeat beyond the scope of its lifecycle. This allows the application to perform some function even after the application process or all of its Android components have been cleaned up by the system.
Typically, the AlarmManager is used to fire off a PendingIntent that will start up a Service in the future. The AlarmManager triggers Services based on an elapsed interval or at a specific clock time. Both of these options also have the ability to wake up the device when it is asleep if the alarm is urgent.
The benefits of the AlarmManager come into play when using inexact intervals or times to fire off Services. The Android system tries to batch alarms with similar intervals or times together in order to preserve battery life. By batching alarms from multiple applications, the system can avoid frequent device wake and networking.
One concern to consider while using the AlarmManager is that alarms are wiped out during device reboots. Applications need to register the RECEIVE_BOOT_COMPLETE permission in their Android Manifest and reschedule their alarms in a BroadcastReceiver.
Another concern is that a poorly designed alarm could cause battery drain. While the AlarmManager does have the ability to wake devices and set an exact time for an alarm, the documentation mentions that developers should be wary of these features when performing networking. Aside from draining a device’s battery by avoiding batch alarms, setting an exact time for an application to sync with a server could put high strain on a server if every application installation tries to sync with the server around the same time! This can be avoided by adding some randomness to alarm intervals or times.
AlarmManager is a great candidate for scheduling if an application needs to perform a local event at an exact time or inexact interval. Alarm clock or reminder applications are great examples for AlarmManager usage. However, the documentation discourages using AlarmManager for scheduling network-related tasks. Let’s take a look at some better options for networking.
Job Scheduler
JobScheduler helps perform background work in an efficient way, especially networking. JobServices are scheduled to run based on criteria declared in JobInfo.Builder(). These criteria include performing the JobService only when the device is charging, idle, connected to a network or connected to an unmetered network. JobInfo can also include minimum delays and certain deadlines for performing the JobService. Jobs will queue up in the system to be performed at a later time if none of these criteria are met. The system will also try to batch these jobs together in the same manner that alarms are scheduled in order to save battery life when making a network connection.
Developers might be concerned about a scheduler that frequently delays firing off its JobServices. If jobs are frequently delayed and data stale as a result, it would be nice to know about such things. JobScheduler will return information about the JobService such as if it was rescheduled or failed. JobScheduler has back-off and retry logic for handling these scenarios, or developers could handle those scenarios themselves.
Subclassing JobService requires an override of its onStartJob(JobParams params) and onStopJob(JobParams params) methods. onStartJob() is where callback logic for jobs should be placed, and it runs on the main thread. Developers are responsible for threading when dealing with long running jobs. Return true to onStartJob() if separate thread processing needs to occur, or false if processing can occur on the main thread and there is no more work to be done for this job. Developers must also call jobFinished(JobParameters params, boolean needsReschedule) when the job is complete and determine whether or not to reschedule more jobs. onStopJob() will get called to stop or cleanup tasks when initial JobInfo parameters are no longer met, such as a user unplugging their device if that parameter is a requirement.
There might be a lot to think about when implementing a JobService, but it comes with a lot more flexibility than AlarmManager. Another handy feature is that scheduled jobs persist through system reboots.
There is at least one drawback to using JobScheduler. As of the writing of this post, it’s compatable only with API level 21 and higher. Here you can find the distribution of Android devices running various API levels. While there is technically no backport of JobScheduler, a similar tool is GCM Network Manager.
REFERENCE LINK

Android - JobScheduler or BroadcastReceiver?

In my Android app I need to do some work every time the user plugs their device. For this purpose right now I use a BroadcastReceiver, which starts my IntentService to do the work when the user plugs the device and stops it when the device becomes unplugged.
Right now I'm thinking of using JobScheduler for Android 5.0+, but what I'm seeing is that with JobScheduler, I would have to schedule my job within the app, by calling
JobScheduler.schedule(JobInfo);
But this is a problem to me, because I want my job to run every time the user connects their device to the charger, even without the user having to open my app.
For this reason, I think one way would be to schedule it the first time the user opens the app, and then always force reschedule, since I cannot trust on the user opening my app every day (which, due to the nature of my app, certainly won't happen).
So, should I stick with BroadcastReceiver or use JobScheduler for Android 5.0+?
And in the case of using JobScheduler, should I schedule my job only once and then always return true in order to force rescheduling?
Thank you.
So, should I stick with BroadcastReceiver or use JobScheduler for Android 5.0+?
Use JobScheduler, this can improve your app’s performance, along with aspects of system health such as battery life. Also, JobScheduler persists through device reboots and supports batch scheduling by which the android system can combine pending jobs thus reducing battery usage. Moreover, you can do distinguish between android versions thus using JobScheduler on Lollipop and up, and AlarmManager on older versions.
And in the case of using JobScheduler, should I schedule my job only once and then always return true in order to force rescheduling?
Now, there are 2 ways to do this :
As you guessed, scheduling your job only once and always returning true in jobFinished() - this should do the trick.
Upon completing a job (originally scheduled by you by calling JobScheduler.schedule(JobInfo)), you schedule another job by calling the same. This will schedule consequent jobs once each job is about to be completed.
Jobscheduler runs in the background and persists through reboots so you should be fine.

Categories

Resources