JobScheduler run job at most once every time the conditions are met - android

NOTE: THIS IS NOT A DUPLICATE, PLEASE READ THE QUESTION
I want to run a job every time the device is Charging & ON WIFI. This job has to run at most once every time these conditions are met.
This means that if I leave the phone charging overnight with wifi ON the job should not repeat itself.
Only when I unplug and replug the job is allowed to execute again. Same goes for when I turn wifi off and on.
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
//.setPeriodic(TimeUnit.SECONDS.toMillis(10))
.setPersisted(true)
Job scheduler provides methods like setPeriodic but that will run my job every X amount of time. Not really what I want.
The job is not critical, I don't need it to be executed right away after the conditions are met, and I'm also OK with it not executing at all sometimes (meaning it's ok for it not to be run when conditions are met for a short period of time)
Is it possible to achieve this using job scheduler? The documentation on this is pretty scare.

If you're not using setPeriodic, then your job would only run once when your other constraints are set. However, your requirements mean you need to schedule a new job when you leave those conditions - JobScheduler does not offer that API, nor does Android offer any API that does that that also works with Android 8.0's Background Execution Limits (with the exception of continuously running a foreground service).

Related

Detect Connectivity Change When App is Killed/In Background

I'd like to detect when there is a network change (connection\disconnection) when my app is not in the foreground, so I can sync the user's data.
I have tried to use a broadcast receiver (like in this answer) but the broadcasts are no longer received when the app is closed (after Android N). It only works when the app is in the foreground.
In order to detect connectivity change in the background, I have tried to use the Job Scheduler (like in this answer) with the .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) parameter, but my problem is that the job is done repetitively (every 15 minutes), even when the user is still connected to the internet.
My goal is to make the job once when the internet connection is regained, and then stop the job until the user disconnects and connects again. The job should be done once for every connection to the internet, and then wait until a reconnection (without repeating it).
Is it possible to achieve this with the Job Scheduler (or in any other way)?
Is it possible to achieve this with the Job Scheduler?
Answer - I don't know BUT
You can use WorkManager. That is part of Android Jetpack.
There are 2 options.
1) OneTimeWorkRequest (that what you need).
2) PeriodicWorkRequest (executes periodically, min time is 15 minutes, same as jobScheduler).
WorkManager executes only 10 seconds, as jobscheduler.
Why is WorkManager good. Image in below will give answer.
Documentation - https://developer.android.com/topic/libraries/architecture/workmanager

WorkManager setRequiresDeviceIdle is confusing

I have implemented a scheduled work manager. My idea is to complete a process every 2 hours. But I need guaranteed execution. According to Work Manager's documentation every enqueued process will be executed guaranteed.
But now this setRequiresDeviceIdle is getting me confuse. It is stated in the documentation that by default setRequiresDeviceIdle has set to false. So what I assumed is that my process will not work if the device is in idle mode.
And Idle mode = When the phone is screen off for some interval.
But If I set this setRequiresDeviceIdle to true. I assume that now it will only work when device is in idle mode.
I want process to be complete even device is in idle or not in idle. What should I do now?
If you go through the WorkManager Docs, you will find:
requiresDeviceIdle boolean: true if device must be idle for the work to run
If you pass true, it means that your work will be executed only when device is in idle state.
As you mentione you want your task to be executed always. Hence, you should pass false in setRequiresDeviceIdle().
Note: It's not necessary that your task will execute exactly after 2 hours. According to the DOCS, your task might be deferred till next maintenance window. You task would be executed for sure, but the duration won't be exactly 2hrs. It might be a little more than that.
In Doze mode, the system attempts to conserve battery by restricting apps' access to network and CPU-intensive services. It also prevents apps from accessing the network and defers their jobs, syncs, and standard alarms.
Periodically, the system exits Doze for a brief time to let apps complete their deferred activities. During this maintenance window, the system runs all pending syncs, jobs, and alarms, and lets apps access the network.
If you wan't your task to be always executed and at exact time, you can use Alarm Manager and setExactAndAllowWhileIdle(). But this practice is discouraged, as it is not good for battery performance.

Android N: dealing with lack of CONNECTIVITY_CHANGE

My AppWidgetProvider (which is of course a BroadcastReceiver) is registered to receive CONNECTIVITY_CHANGE, so that I can update the widgets as soon as network is restored (though only if required, i.e. if a previous update was missed due to lack of connectivity).
But as set out here, this will no longer be possible in Android N. The suggestion is to use JobScheduler, which allows you to specify that the Job should run only when connected to a network by way of the .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) method.
However, I can't see how this can be used to replicate my desired behaviour. It seems to me that the .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) method will cause the Job not to run at all if there is no network at the time that the Job is scheduled, and it will not cause the Job to wait patiently until there is a network and then run (which is what I need).
So, how do I retain the behaviour I need, with Android N?
I am using Job Schedulers and it does not depend on whether network is available or not while scheduling the job. It provides certain conditions and when those conditions are satisfied job is scheduled. You can set a repetitive job and also specify minimum time gap between the jobs. For example whenever I connect my phone to charging PlayStore start updating apps as the Job has charging constraint.
If you schedule a job and conditions are not met, it will schedule when network is available. Try to disconnect network and open someone profile on Facebook. It will ask you to load profile on network availability. Now, connect to network and you will get the notification once profile is loaded.
try to add google ping for network change that will help you for
network change and all cause i have same issue when i was developing
with socket services. So may be it will also helps you.

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.

Jobscheduler API android L

I am making an application that makes use of the jobscheduler API.
I want to run a service periodically and when the device is charged. This is the code.
JobInfo.Builder builder = new JobInfo.Builder(kJobId++, mServiceComponent);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
builder.setPeriodic(3000);
builder.setRequiresCharging(true);
mTestService.scheduleJob(builder.build());
Now when I run this and I unplug the device, the service still runs after 3 secs. There is no effect of setting the setRequiresCharging.
When i comment out builder.setPeriodic(3000), it works perfectly fine. I am not sure as to where I am going wrong.
To identify each job internally, the framework creates a new JobStatus when a new job lands on the scheduler. One of the first things JobStatus does is to check and see if your job has a periodic update interval. If it does, it uses the periodic update interval to determine the latest point in the future that a job must be run, or in other words, if it has a deadline constraint.
One of the criteria for a job to be considered ready to be executed, it that all of its constraints have been satisfied or the deadline of a job has expired. See JobStatus.isReady for more information.
The JobSchedulerService adds several StateControllers used to track when jobs should run and when they must be stopped. One of these controllers is a TimeController, which:
sets an alarm for the next expiring job, and determines whether a
job's minimum delay has been satisfied
To determine if a new alarm should be scheduled, TimeController checks if your job has any time delay or deadline constraints, which all jobs seem to be given if you set a periodic update interval.
I hope that helps you at least understand why your job continues being scheduled despite your battery constraint. But I don't have a solution that can offer a straightforward fix for this at the moment.

Categories

Resources