Scheduling JobService to run only when app is running (on foreground) - android

I need to do some background updates (about every 1 min). I have to use JobService to do it periodically. But I don't need to run service when app is closed - only when app is running (on foreground).
Is there is a way to do that?

You don't need a JobService for that. Simply use normal Service. The OS allows apps in foreground to freely create the service. You can easily start a Service and perform your task. You can use Handlerthread for background processing or use Handler for foreground processing.
Note for Android O: If your app goes to background then your Service will be stopped as if you have called stopSelf(). Remember to clean up the necessary object's state.

Related

Having an Android service as both background and foreground service

I've read that I should call
startForegroundService(intent)
if I want to properly start a service that can run as a foreground service. But how should I think if I want it to start without it being a foreground service but potentially becoming one later on? Some info on how we have it right now:
We have an App which uses a service for many tasks. It performs all of these task when the user interacts with the app in the foreground but depending on if the user has enabled a certain feature we want to keep performing these tasks in the background. So when the app is launched (and obviously is in foreground) we start the service using
startService(intent);
When the app transitions into background we check whether the feature is enabled, and if so, run startForeground(id, notificiation); which effectively adds the non-removable notification out in the OS and the service keeps on running. When the app goes back into foreground we call stopForeground(true). If the feature isn't enabled the service will never be set as a foreground service and we won't try to perform these tasks in the background.
So my question is: Is this sufficient to get the "full foreground service performance"? Or am I losing something by not calling startForegroundService(intent)? My impression is that we actually do have a fully working foreground service but I'm getting confused when I read statements that foreground services must be started using startForegroundService(intent) which we're not doing. If we really need to use startForegroundService(intent), the only solution I can think of would be to initially start a normal instance of the service and when the app enters background we start a new one using startForegroundService(intent). But do we need to do this or is running startForegund(id, notification) on a service started using startService(intent) sufficient to achieve a foreground service?
NOTE: One difference I find is that if the application itself is in background when start the service I then need startForegroundService(intent) for API >= 26. In our case we always start the service when the app is in foreground. I do however recall some instances where I've seen the exception thrown when we try to start the service using startService(intent), somehow the app (very very rarely) still think it's in background (perhaps something from the OS comes up just when app is launched). So if I catch when that happens I could run startForegroundService(intent) to start the service. But is it possible to run stopForeground(true) on that service when the app comes back into foreground? Or is it bound to be a foreground service forever since we started it that way?
Seems like you don't have to call startForegroundService and startService is sufficient:
If your service is started (running through Context#startService(Intent)), then also make this service run in the foreground, supplying the ongoing notification to be shown to the user while in this state. By default started services are background, meaning that their process won't be given foreground CPU scheduling (unless something else in that process is foreground) and, if the system needs to kill them to reclaim more memory (such as to display a large page in a web browser), they can be killed without too much harm. You use startForeground(int, Notification) if killing your service would be disruptive to the user, such as if your service is performing background music playback, so the user would notice if their music stopped playing.
From Documentation
I read your question multiple time and I think (hopefully) the answer to your question is :
According to the official document of Android 8.0 Background Execution Limits:
Android 8.0 introduces the new method startForegroundService() to
start a new service in the foreground. After the system has created
the service, the app has five seconds to call the service's
startForeground() method to show the new service's user-visible
notification. If the app does not call startForeground() within the
time limit, the system stops the service and declares the app to be
ANR.
So, make sure you have started ongoing notification by calling startForeground (int id, Notification notification) in the onCreate() method of your service.
Note: Apps targeting API Build.VERSION_CODES.P or later must request the permission Manifest.permission.FOREGROUND_SERVICE in order to use this API.
And there is great medium article posted by Maciej Witowski that help you understand how really new services API works :
https://proandroiddev.com/pitfalls-of-a-foreground-service-lifecycle-59f014c6a125

background task questions

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

Make a service run indefinitely and communicate with activity

I Can't understand the differences on android services
I want to have a service run all the time in the background (activity recognition)
When it detect that I RUN -> open GPS -> save curent longitude latitude -> if I stopped to run (WALKING) -> display the log lat on my MainActivity
i want the service run if the user close the app , if the device is closed and re-open , if my service is killed
so I read about:
[Started Service , Intent Service , Bound Service , Intent Bound Service , Job Scheduler , Job Intent Service].......But still i missing something
I understand that with Service start_sticky for API<26 will run forever (if not killed) and with IBinder I can update the UI of my MainActivity; right?
My Many Q are ...:
1. Bound services can run for ever? and update my UI of MainActivity? do i need bound or i can achieve this with service or intent service
2. For oreo I "must" use Job Scheduler -> when killed -> open again with broadcast receiver || work manager || alarm manager ||?
My questions are more for theory Answers not code.
NEED to -> service for "ever" run -> if (something) -> open gps -> save long lat -> show long lat in UI of MainActivity.
To keep a Service running indefinitely in the background, use a foreground service. This will force you to maintain a visible notification/nav bar icon; that's the price Android extracts from you in exchange for keeping your service running for a long time period. Supported on API 5+.
JobScheduler/WorkManager/AlarmManager won't prevent your Service from being killed. They can be used to bring your Service back to life. Also, JobScheduler and WorkManager can get your system out of doze, so you can do useful work. A WakeLock may also be necessary. If the user explicitly terminates your app, JobScheduler jobs will no longer wake it up. I don't know of any good, "Android-approved" way to resuscitate an app in this circumstance. Although, even on Oreo+, you can register to receive these intents, which you can use to regain execution.
You can make any of the Service subclasses you mentioned into a foreground service (by calling startForeground(). The choice of subclass is a matter of convenience, and depends on how you would like to dispatch & schedule your work. Your app could just as easily be implemented with the base-class Service.
START_STICKY doesn't actually prevent a Service from stopping. It's more like a request to the system: "After you kill my app/service, please restart it, if/when you see fit". In my opinion, it is not an effective way of keeping a Service running for a long period of time. If a Service is not in the foreground, and no other application components are in the foreground (e.g., on screen), then Android can kill your app quite quickly. This is more true of later versions of the OS (Oreo+).
Your Service will need to be bound to other components (e.g., Activities) from time to time. You bind to a Service so you can 1.) Make sure it exists and 2.) Carry out communications with it (call functions on it, etc.). So, yes, with IBinder, you can update the UI of your MainActivity.
Binding a Service doesn't make it run forever. If your Activity is bound to the Service, you can be confident that the Service will stick around for as long as the Activity is onscreen. Once it leaves the screen, all bets are off.
In other words, Android is very likely to kill an app/service when it's not in the foreground, and not bound to any components that are in the foreground (onscreen).
A Service can generally open up an Activity at any time it chooses, simply by calling startActivity(). Your Activity can even dismiss the keyguard (in certain circumstances), using FLAG_DISMISS_KEYGUARD.
If you can tolerate less frequent location updates, you may be able to do this without staying in the foreground, but there are limitations.

Create a Long Running service

I need to create a service that runs alongside the android app,irrespective of which screen of the app the user is on.
The app is a chat application so when the device is offline the service should queue up all the messages that are being sent offline and when the device is connected it should sync all messages.
I have written code for the job scheduler to sync data automatically when the device is online but while the app is active i would like to handle this manually.
Creating a Long Running service.
Operating system still can terminate the service in low memory and possibly other situations. There are 2 ways to overcome this:
If you are implementing the service, override onStartCommand() and return START_STICKY as the result. It will tell the system that even if it will want to kill your service due to low memory, it should re-create it as soon as memory will be back to normal.
AlarmManager .A system service, which will execute actions periodically. That will ensure that if your service will be terminated, or even the whole process will die(for example with force close) - it will be 100% restarted by AlarmManager.
Thank you.
You can do this by simple following steps:
Create Simple Service and after first launch of app just start at splash screen.
In Service after getting one data you can call another request.
After that you can create one broadcast action globally which will always call every network changed.
At background you can sync again data and saved it to shared preferences or as per your your requirement.
For interval you can also using AlarManager.
A part from this you can simply create Service using JobSheduler in this you can assign job and time as well.
Refer link :
https://developer.android.com/reference/android/app/job/JobScheduler.html
Hopefully this logic will helps you.
You have to use a intent service with sticky instead of service for this which will be executed in a queue and do your work. And since it is a intent service it will be started automatically after sometime, when system kills the service process.

How to make service running even after manually swiping off of recent apps?

I am trying to build a count down timer that runs in the background in a separate thread. I am using a foreground service and passing a handler to the background thread from this service. So essentially, the activity will communicate with the service and the service will communicate with the thread.
Essentially, when the user swipes the app off from the recent apps, i need the timer to keep running.
What is the best design that does this?
You will need to use a started Service and startForeground().
Check this question for details.
Also if you create service in a separate process it will solve your issue.
Here is a great tutorial
A started service can use the startForeground(int, Notification) API
to put the service in a foreground state, where the system considers
it to be something the user is actively aware of and thus not a
candidate for killing when low on memory.
Like Ivan previously said, it is a combination of startService(), binding calls and startForeground() call to keep the service running in the background. Don't really require a separate process to do this.

Categories

Resources