In my app, I am using ffmpeg-kit and execute a command that record/capture any stream using the internet and writes it to the device's internal storage.
This command or stream can run until the user stops. And from here you can get an idea of this task that this execution can be 10 min, 30 mint or even 1 hr or more depending on the user till he wants to stop or the stream it self complete. e.g: video ends
Now my constraints are regarding this task that the app runs this FFmpeg command in the foreground and background but doesn't need to run when the app is killed by the user or system.
This task is only present and running while the app is running either in the foreground or background.
So now I need a suggestion from experts on which android services are best for use in this case.
I run across a few of them...
IntentService, JobScheduler and WorkManager
I've thought of using WorkManager here but my work is not persistent here and neither I need to run the FFmpeg and record stream while the app closed..so WorkManager is not suitable for this scenario.
None of those is the right answer. IntentService isn't a solution, as background services get killed in 2 minutes. JobScheduler would have the same problem- processing time limitations. As would Workmanager.
What you want is a foreground service. Foreground services are services that can run for long times (they will still also be eventually killed, but can run for hours). Foreground services are launched by using startForegroundService instead of startService, and require the Service to call startForeground and provide a notification that will be in the status bar as long as the service is running.
Related
In my app, the user can start a background process that makes long running API calls to the backend. The user will also have the ability to pause the background thread and resume at any point.
If the app restarts, the background process should resume from where it left off. Once the background process has completed, the process should terminate.
Even when the background process is running, if the user hits the device's home button, I still want the background process to keep running. It is not necessary for any UI to be shown while it is running.
Reading up on the Android docs, it would seem that using WorkManager is probably the best choice since my minSdkVersion is 19. Is this true?
The process can run for hours
WorkManager work cannot run that long. You could still use WorkManager for the scheduling aspect, but then the "work" would need to be starting a foreground service, where the service then does the actual network I/O.
It is not necessary for any UI to be shown while it is running.
On Android 8.0+, you cannot have something running for hours without UI showing, at least in the form of a Notification associated with a foreground service.
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'm writing an Android application that records video and then runs post processing on recorded video. Since post processing may take a while (up to an hour) I'm scheduling a service - JobService using JobScheduler to run when the phone is connected to power and idle i.e. to run at night.
The job service doing the long-running job on a new thread.
In practice my scheduled service is working VERY slow. It seems that although it runs when system is idle, it gets very little CPU bandwidth. Also my service is being stopped after 10 minutes max by the OS.
I know Android Oreo limits background processing. This is well documented by Google. However I'm wondering if there is a way to run background services when system is idle.
Is there a way to run long background services when system is idle? For example video post processing?
You need to use a Foreground service.
They are one of the few methods left to run long background tasks. The user must know what's happening on his device and he should have the ability to decide to stop it or not.
You can read how to implement basic Foreground Services here, and there are a lot of guides on the internet on how to implement them in an advanced manner.
Remember that even a Foreground Service can be stopped by the OS if the system is in extreme memory pressure and the only things left to destroy are foreground services. So you should always have a recovery procedure if that happens.
https://developer.android.com/about/versions/oreo/background#migration
As per document, Google allows only below things as a background processes,
Handling a high-priority Firebase Cloud Messaging (FCM) message.
Receiving a broadcast, such as an SMS/MMS message. Executing a
PendingIntent from a notification. Starting a VpnService before the
VPN app promotes itself to the foreground.
also,
While an app is in the foreground, it can create and run both
foreground and background services freely. When an app goes into the
background, it has a window of several minutes in which it is still
allowed to create and use services. At the end of that window, the app
is considered to be idle. At this time, the system stops the app's
background services, just as if the app had called the services'
Service.stopSelf() methods.
Under certain circumstances, a background app is placed on a temporary
whitelist for several minutes. While an app is on the whitelist, it
can launch services without limitation, and its background services
are permitted to run. An app is placed on the whitelist when it
handles a task that's visible to the user, such as:
Query is,
My App (targetSdkVersion 26), which needs to be download a large file(~100 MB) in background (a state, app not exist in recent list even). I have create a Service to achieve this, but as I am removing my app from recent, my download get stops. So, Google does really means, an app cannot execute a download process in background with targetSdkVersion 26?
Google does really means, an app cannot execute a download process in
background with targetSdkVersion 26?
It imposes restriction on executing a Service in background. However you can still get your job done in background.
Approach 1:
If it really takes very long to download your necessary data, you can make use of new WorkManager API.
As the documentation say, WorkManager is intended for tasks that require a guarantee that the system will run them even if the app exits, like uploading app data to a server. It is not intended for in-process background work that can safely be terminated if the app process goes away.
You can schedule a work which can be one time job or periodic. Moreover it also allows you to specify constraints, like internet connectivity required. This should be preferred for deferrable or asynchronous tasks.
Approach 2: Create ForegroundService
Alternatively, you can start a ForegroundService immediately and execute the task before terminating the Service. You might need to request for partial wake lock in some cases.
You can also look at my answer on this SO for more details.
I am parsing all text messages from the device and extracting words from them. For doing this I first used Service, but the issue with it was that it made application slower or sometimes I got notification that Application is taking longer to run.
Alternative to this I used IntentService. But problem with intent service is that whenever I stopped the application, I couldn't see my service running anymore. Alongside I also have to use Alarm Manager to schedule the things.
I am planning to use SyncAdapter for doing both of the things, but I don't think it would be a good option to use it. It would be really helpful if there is a better possible for doing this.
Background task might take upto 5-10 minutes for completion and I am planning to run it in every 12 hours. Though I won't be parsing old messages again. So it won't take longer after first time. The task should not end even when application is closed.
Basically IntentService is apt for background tasks which are not tied to the application lifecycle.
But problem with intent service is that whenever I stopped the
application, I couldn't see my service running anymore.
You can send updates to UI from intent service by using:
LocalBroadcastManager: how to use LocalBroadcastManager?
Handler: How to Collect info from IntentService and Update Android UI
Also you might want to see this video: The Zen of IntentService. (Android Performance Patterns)
EDIT:
Forget about using IntentService, it stops as the app stops because it runs on the same process as the app.
Since you want your service to work as a job every 12 hours, you could use a 'Scheduled Service'.
You can use JobScheduler or Firebase JobDispatcher API