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
Related
I am developing a flutter application, however I would like a service to be able to run constantly without stopping in order to make an api request every 15 minutes and then send a notification to the user (Android /IOS). I would also like the service to start automatically with the smartphone. I've been stuck on this for more than a week now and I've been browsing the forums looking for a solution but I can't find what I'm looking for. Thank you in advance for any help
You don't do it like that on Android. You cannot count on an application not being killed in the background. Instead, you use JobScheduler or WorkManager to set an alarm and wake you up every so often to perform whatever job you need. These methods can also ensure you're scheduled at startup of the phone.
Also, 15 minutes may or may not happen- Doze mode may cause your app to be delayed and make requests less frequently than that if the phone goes to sleep (although 15 minutes is fairly safe, plus or minus a few).
I have been reading lately about how background jobs are done in Android (using Service, AlarmManager, JobScheduler, etc) and learned that these background task can go indefinitely even the app has already closed or device has screened off. I understand that the only they stop if they stop themselves or other components stop them.
Questions:
If I have a background job or an alarm that goes every 1 hour. Does it really runs forever until a component stop them? Is there an instance that the system will stop them?
What if I have periodic job or alarm that goes every 1 hour. Will they stop if I uninstall the app that started them? Cos I never read this part in any documentation.
Is there a way to check any running or pending background jobs/alarms in my device?
The explanation that is given about background tasks in your question only applies to Background Services, that to only in Android API Levels below 26.
Google recommends using JobScheduler or Foreground Service to do some work in background even when app is not in foreground.
Coming to you questions
No, If your using JobScheduler or Alarm manager the system will trigger your job to do your work depending on device idleness and conditions mentioned by you but the system can anytime come and stop your work in between when the conditions are no longer met.
If your are using JobScheduler it will inform you when system wants to stop by force so that you can handle it properly and reschedule if needed
When the App is uninstalled every job or alarm that is scheduled or in-Progress will be destroyed.
Yes, JobScheduler does provide a function 'getAllPendingJobs'
Note :
For works that should be scheduled or completed even when app is closed then try avoiding the use of Background Services or Alarm Managers.
JobScheduler is much more better replacement.
If you want to do some simple background work when the app is in foreground then try using HandlerThreads or AsyncTasks
I want to call web service in the background when internet is connected. If it is connected I want to call in every one hour if internet is turned off then stop the service. How can I? It needs to work for all versions from 16 to 27.
There is broadcast in android which notifies you if network status changed. In there you can register alarm manager for a period of one hour and check if the internet was connected then call the web service.
If broadcast informed you the network was disconnected then you can cancel your alarm manager.
Here is documentation for listening to network status change:
https://developer.android.com/training/monitoring-device-state/connectivity-monitoring
and here is good tutorial about using alarm manager in android
https://en.proft.me/2017/05/7/scheduling-operations-alarmmanager-android/
also google introduced workManager which does this work for you in the very simple way
The WorkManager API makes it easy to specify deferrable, asynchronous
tasks and when they should run. These APIs let you create a task and
hand it off to WorkManager to run immediately or at an appropriate
time. For example, an app might need to download new resources from
the network from time to time. Using these classes, you can set up a
task, choose appropriate circumstances for it to run (like "only while
device is charging and online"), and hand it off to WorkManager to run
when the conditions are met. The task is still guaranteed to run, even
if your app is force-quit or the device is rebooted.
here is link to documentation :
https://developer.android.com/topic/libraries/architecture/workmanager
Basically what I want to do is, when there is an internet connection then collect values from sensors and schedule the next time data is collected from sensors, let's say 5 minutes (this interval depends on the current activity: walking, running...). After 5 minutes, the system checks if there is internet connection:
-if there is then the cycle is repeated (collection, sending to server and scheduling the next data collection)
*if there isn't then the next time the data is collected is scheduled for the next time there is an available internet connection
What I tried using:
1) I wanted to use a broadcast receiver for api<21 and job scheduler for api>=21.
For job scheduler, I can't set requirement available network and make the job periodic at the same time because this way the job runs after the period is over whether the requirement is met or not.
2)I tried to make the job service set the next job after the current one is over but the app ran as if that part of the code didn't exist (it only ran once)
3) I tried to somehow combine job scheduler with alarm manager to make the job scheduler manage the network requirement and the alarm manager manage the periodic aspect of the job. But I failed to implement this and I feel like this isn't the right way to do it.
If someone could guide me to a better way to handle this, I'd really appreciate it because I've spent a long time trying to solve this.
I would recommend a library from Evernote called android-job. It handles all the complexity of choosing JobScheduler on 21+, Firebase/GcmNetworkManager, or AlarmManager and all kinds of other things. It has a pretty robust set of features that should fit your use case.
For Example:
int jobId = new JobRequest.Builder(DemoSyncJob.TAG)
.setExecutionWindow(30_000L, 40_000L)
.setBackoffCriteria(5_000L, JobRequest.BackoffPolicy.EXPONENTIAL)
.setRequiresCharging(true)
.setRequiresDeviceIdle(false)
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
.setExtras(extras)
.setRequirementsEnforced(true)
.setPersisted(true)
.setUpdateCurrent(true)
.build()
.schedule();
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.