Android 12 - Foreground service launch restrictions - android

I'm developing an SDK that needs to startForeground service from the background. Because it uses background location and Bluetooth-related works. If the application is killed, the monitoring is performing in the background. That's why I'm using the foreground service. There is a condition that starts the foreground service from the background.
Currently, my SDK using Service to handle this job. But Android 12 on-words it doesn't support to start service from the background.
I'm trying to start the service from the background the below exception throws.
ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false
How can I use WorkManager to fix this issue, all my handling is done by the Service class and how can I pass the Service object to Worker class and start this job inside the Worker class.
Actually, my project is based on beacon technology.
and the beacon signals are used to show different recommendations to the user.
In my current implementation, if the application is killed by the user,
and also accepts the foreground service, the SDK will be run in the background.
and detect the beacon and provide appropriate actions.
My implementation is that, if the application initializes my SDK with the foreground service "OFF"
Then sometime later, when the application is in the background and trying to start the foreground service from the background this exception throws.
The foreground service-related decisions are held by the server-side API. I'm periodically checking whether the server-side value is changed or not, and if the value is changed the changed action is reflected in the SDK.

There is no one in the world that can give you an answer. The idea of all these restrictions is that we as developers need to optimize our applications. So if this is not possible for you it means most likely that you need to optimize the way you do your work. For this to happen you need to provide more info of what exactly events you are receiving, what is exactly your use case, etc.
https://developer.android.com/about/versions/12/foreground-services#cases-fgs-background-starts-allowed
As you can see there is info about exceptions for:
Your app receives a Bluetooth broadcast that requires the BLUETOOTH_CONNECT or BLUETOOTH_SCAN permissions.
But there is nothing in your question saying that your use case might relate to this.
Also, I don't understand how the app might be killed, but you keep working in the background.
Also if you want to constantly do something - why there is an event when you are in the background. Just when the user opens the app - start the service and keep it going.
You can also just "hack" it and ask the user to remove you from battery optimization.
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases

Earlier we were using Service to run background tasks. But, due to Android 12 - Foreground service launch restrictions, we will not be able to invoke Service for performing background tasks for Android 12+.
So from now on, from targetSdk 31, Service can be invoked only when the application is in the foreground. When the application is closed or when the application went to the background, invoking Service using startForegroundService will cause ForegroundServiceStartNotAllowedException.
So to perform background tasks, we need to use Worker instead of Service. Please refer to this answer to get an idea of how it is implemented. Hope it helps. Also, refer to the below links to get a high-level overview of what changes needs to be done.
Android 12 Behavior Changes
Work Requests

According to the official docs, if your app does one of the following, it should be able to start an FGS:
Your app receives a Bluetooth broadcast that requires the BLUETOOTH_CONNECT or BLUETOOTH_SCAN permissions.
or
Your app receives an event that's related to geofencing or activity recognition transition.
Those two seem like pretty good candidates for your use-case, at least how I understood it.

Related

Difference between Foreground service vs Activity in android

I am trying to create one hobby app on Android rooted device. In this app there is no need for user interaction as well and app need to run continuously . I am trying to use some sensors (accelerometer/gps) and camera also.
I have 2 approaches for this implementation as mentioned below-
1- Single Activity with Kiosk mode
2- Foreground Activity starting from application class
So I am looking for pros and cons for both the approaches in terms for battery , some background tasks etc.
Does doze mode/screen sleep impact activity and foreground service differently?
Edit-1
I am using custom ROM for my embedded project . I need to keep it for single application and user interaction is not there. I was thinking for better approach for my project in that case.
If I understand your question correctly, you're asking about creating an app that runs some sort of task without an active user. In this case, you're looking into deferred and exact tasks.
You can use WorkManager to schedule tasks to be executed at the exact time.
As for the services, there is a distinction between foreground and background ones. Please note that Android opposes certain background execution restrictions when you're targeting SDK versions 26 and above. With foreground services, you're required to display a status bar notification.
The documentation clearly states that the use of WorkManager is preferred over starting a foreground service. I would advise you to read this Medium article for more information.

Foreground service vs WorkManager for location tracking

Let's say I want to build an app which requests current location periodically (e.g., every 10 minutes, this number should be configurable) and submits to a server.
I'm aware that Foreground Service and WorkManager are normally suggested for this kind of scenario. However which is would suit more? Below are my thoughts and doubts.
WorkManager - is mainly for deferrable background work whose execution is guaranteed. However I know that from Android 8 (API 26) background location was introduced and that restrict location to be updated only a few times every hour https://developer.android.com/about/versions/oreo/background-location-limits. Thus this perhaps doesn't meet the periodical updates as per the requirement.
ForegroundService - is perfect for something that runs and needs to make users aware of. It's recommended for this kinda scenario (location tracking) for privacy purpose. Google also creates a sample app to promote this practice https://github.com/android/location-samples/tree/master/LocationUpdatesForegroundService.
From the above analysis, it seems ForegroundService is the one. However I also found that WorkManager has a built-in support to use Worker in conjunction with ForegroundService via androidx.work.impl.foreground.SystemForegroundService https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running#long-running-kotlin
That makes me confused as to what should I use and what Google really recommend for this specific scenario.
Anyone has any idea?
If you want to communicate somehow with the service then use foreground service and if you want to have some processed input based on something else you did in that work manager then choose work manager.
Work manager doesn't have option to redeliver intents and all other commands like start sticky etc...
Since work manager is more suitable for syncing data with db, processing a file etc..
If you were to ask me, I'd choose foreground service since you can add a type location to the xml tag when you register it in the manifest.
Both of these solutions don't survive OEMs aggressive battery restrictions since WorkManager's work can be deferred and if I want instant execution combined with wake locks I can easily do it in the foreground service since it also has a binder option that works well for UI sync.

Storing events to a database while app is running in background

I want my app to store events(fired by an SDK) to a database (using realm) even if the app is in background. My concept was to use a Service that makes some SDK initialization and listening on the events. By starting this Service within the onCreate() method of my custom Application class I wanted to assure that the Service is kept alive while the app is in background so that I don't miss any event to be stored into the database.
But now since Android 8 background services are no more allowed. But I don't want to use a Foreground Service because I would need to display a notification. And I don't want the user to know that events are stored in a database in background. I think that information is to technical for normal users.
I realized the problem when Application.onCreate() wanted to start the service but an exception was thrown:
Caused by: java.lang.IllegalStateException: Not allowed to start
service Intent {
cmp=my.package.name.debug/my.package.name.service.MyService }: app is
in background uid UidRecord{94b2e4a u0a204 SVC idle
change:idle|uncached procs:1 seq(0,0,0)}
Remarkably the exception is thrown if I kill the task of my app. So Application.onCreate() is called if I kill the app.
Finally I am not sure if a Service is the right thing to use for my use case.
I have two questions:
What kind of component to use if I want to store events in a database also if my app is in background?
Why does killing the app trigger Application's onCreate()?
You can use workmanager for your particular case.
It can fulfill all your requirements and it has guaranteed execution even if app is in background or device gets rebooted.
Check this (link to example code for WorkManager) out for more info on WorkManager Api.
I found an answer related to my 2nd question:
I start my Service using Service.START_STICKY. If the app is killed, the service is killed too. A sticky Service recreates itself if it is killed. And because the Application class starts the Service in my case, the Application is recreated, too. But still the app is in background and then I run into Application's onCreate() and the App crashes because Oreo doesn't allow any Service to be started while the app is in background.
Edit:
Answer to my first question: After reading more in Android's official documentation I come to the following conclusion: It really seems that a foreground service is the wrong choice here because the user does not need to know about events stored to the DB. A JobScheduler (or the newer Workmanager) is more for one-time or periodic jobs. So a mixed started/bound service seems to be the right choice here.

keep service running in background in android

I am developing a chat application in android . and need to keep service running
even after exit from application .
I am usin
return START_STICKY;
in onStartCommand() of my service .
but because of limitation of services in android oreo , service will destroyed after seconds when exit from application.
So far users lost new messages notifications.
I can not use Fcm beacause of local networking and no access to internet.
And I can not use ForegroundService . (because Of Employer's request to not showing any notification) .
When I checked running service in android mobile setting , there are some
apps that their service not killing like Es file explorer , Zapya , ...
How they keep their service running without foreground service .
And What should i do .
Show in blow image , some apps services are running without any notification .
Based on the documentation:
The system distinguishes between foreground and background apps. An
app is considered to be in the foreground if any of the following is
true:
It has a visible activity, whether the activity is started or paused.
It has a foreground service.
Another foreground app is connected to the app, either by binding to one of its services or by making use of one of its content
providers.
Reason Es FileExplorer can do could be (its just my opinion) following:
Es FileExplorer (is quite cheeky when it comes to taking advantage of some loop holes) have several content providers but one provider, FileProveders which is some how manages to have com.android.providers.settings connected to it. I guess this connection makes it foreground. They virtually have all the possible intent-filter registered for almost all the scheme. Anything you try to share or access, could trigger them some or the other way which keeps its process in use (you can just click on the details and you will find LocalCService of app running).
But for your app:
If you can't use FCM, ForegroundService and can't have visibility to user, then only option is to perform task periodically. You can use WorkManager. The only limitation is minimum duration for scheduling is 15 minutes. Refer to my answer for scheduling work with WorkManager and WorkManager vs Service for usage of WorkManager.

Is there a way to mark my Android app process "busy"?

I have a downloader application on Android.
It shows a notification(in-progress, not dismissable) during the download
and it also catches a wakelock.
I even asks the user to disable Doze for my app.
However, battery-saving feature from various vendors seem to ignore it and kill it randomly.
Is there a way to mark my app process "busy",
so that it has a higher priority in the not-to-kill list?
Note that I'm not using a service in my app.
Regular activity spawns up a thread and download is handled from there.
Note that I'm not using a service in my app
That would be the lion's share of your problem.
Regular activity spawns up a thread and download is handled from there.
That means that Android has no idea that you are doing anything that the user would value, when you're not in the foreground. Android will happily terminate your process to free up system RAM for other processes.
Use a service, perhaps an IntentService (since it already has a background thread for you, and it automatically shuts down once your work is complete). Convert your Notification into one for startForeground() on the service.
If you are keeping a wakelock for a longish time then it is better to let the user know about it, use a foreground service as CommonsWare pointed out.
However, if your use case does not warrant any foreground behavior then I would recommend you use framework JobScheduler that plays very well with doze and app standby as well.
For earlier than API 21 you may use JobDispatcher API.
You can read the more details here.

Categories

Resources