Question regarding android 12 foreground service launch restriction - android

I have app update broadcast revceiver. i know that it is in list of exception for starting a foreground service in background. but here is what i am doing.
calling startForegroundService in app update receiver
in the newly created service calling startForeground() to show a notification which updates the alarms from database (as the app was updated so i need to again set all alarms as well)
so it this considered valid as per android 12 restrictions or i need to use workmanager to call startForeground method()?

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

BroadcastReceiver that working even when the app is closed

I have a question about BroadcastReceivers. I have an app that needs to receive constantly the ACTION_TIME_TICK intent to refresh the clock widgets. I implemented a foreground service which contains a BroadcastReceiver that listens to that action. But on android oreo the only way to start a service is starting it as foreground service which implies to show a persistent notification to the user which notify that the app is working in background.
I don't want to show to the user that notification. I tried to implement BroadcastReceiver inside the Application class. But this is not working proprely. Somethimes the BroadcastReceiver doesn't work and somethimes works well. Even when it works well, if the app is removed from the recent tasks, the BroadcastReceiver stops to work. Is there a way to use a BroadcastReceiver that works indefinitely without the use of a service?
Is there a way to use a BroadcastReceiver that works indefinitely without the use of a service?
In the case of ACTION_TIME_TICK: No, since you cannot use a manifest-declared BroadcastReceiver.
Since you're not willing to use a foreground service, you may want to look into START_STICKY. In this situation, that's the only way to maximize your Service's run-time: Allow the system to re-start it, capriciously, after it's been stopped for lack of resources. Of course, this means your clock could stop updating for arbitrarily long periods of time.
Note that your problem is not limited to Oreo (Oreo does not require you to be a foreground service, but it does impose certain limits on what you're allowed to do if you're NOT in the foreground). Even on earlier OSs, if you're not foreground, the system considers you a prime candidate for elimination.

Context.startForegroundService() ANR without actually calling it

After updating my app to target API 27 (previously 25) I'm encountering many ANR's from users, which I can't reproduce. They seem related to the Oreo background execution limits, with the ANR message
Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{73bc351 u0 com.xxx.xxxx/.player.PlayFileService}
However I do not call Context.startForegroundService() anywhere in my code. What are some reasons this ANR could be generated that are not a result of a direct call to this method?
In my case, even though I didn't call Context.startForegroundService() directly, it was being called because my music app would go into the background and the service would be destroyed by the system. Then, when the user pressed a media button to resume playback after a couple minutes, the service would get restarted by the system, with that call since the app was in the background. I did call startForeground() eventually but it was after a bunch of configuration. I added a call to startForeground() at the beginning of onCreate() of my service with a blank notification and all my ANR's have disappeared.
Based on the documentation:
Prior to Android 8.0, the usual way to create a foreground service was
to create a background service, then promote that service to the
foreground. With Android 8.0, there is a complication; the system
doesn't allow a background app to create a background service. For
this reason, 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
You can follow this SO which describes the approach to properly start the foreground service with Notification Channel.

Service started from widget doesn't work in Oreo

When I implemented my widget a couple years ago, I used this advice from the App Widgets page on the development site (still there): "If your App Widget setup process can take several seconds (perhaps while performing web requests) and you require that your process continues, consider starting a Service in the onUpdate() method." I did this and it worked like a charm when built for SDKs up through 25.
It also worked on Android 8.0, but as soon as I targeted 26, the app started crashing in the onUpdate method of the widget provider when issuing the startService call. The error message had to do with trying to start a background service from another background service, and although I tried a few things in the service definition in the manifest I couldn't get it working.
I ended up doing a workaround when I decided that I didn't really need to update the widget from a service, so now just do the update directly in onUpdate. Services and background/foreground issues are something I've not messed with much, but I'd still like to know if there is a way to have kept using a service to update the widget.
in Android O, we have a new background limitations. When you're trying to startService(), you will get IlleagalStateException, so now you should use startForegroundService(), but if you start service by this new method, you will get RemoteServiceException. To avoid this exception you have 5 seconds to make startForeground() after startForegroundService(), to notify user, that you're working in background.
So, where is only one way in Android O:
context.startForegroundService(intent)
And in service onCreate() make something like that:
startForeground(1, new Notification());
UPDATE
So as i assume, some manufacturers have backport on Android N these new background limitations, that's why you can get same exception in Android N.
Without a Minimal, Complete, and Verifiable example, it is difficult to help you. Depending on what you had, you could have:
Switched to JobIntentService, particularly if your old service was an IntentService and you did not mind the possibility of a several-second delay in the work being started
Called startForegroundService() on Context (instead of startService()) to start your service, and in your service call startForeground(), to make your service be a foreground service
Called getForegroundService() on PendingIntent (instead of getService()), and in your service call startForeground(), to make your service be a foreground service

How to set the priority of android service?

Is there any way to set the priority of android service? I want to run the service in background after destroying App's main actvity. So i am returning "START_REDELIVERY_INTENT" from my service. But restarting of service is taking some time (around 1-3 minutes). I want to restart the service instantly. Is there any way to set the priority of android service.
FYI, I am creating service using startService and passing an object through intent.putExtra().
Below snapshot is taken from setting/apps/running apps by my android device, which shows that app is restarting... My app is real time specific, so i want to restart it instantly...
You cannot control this behavior of Service as it depends on the OS and available resources. However, for a continuously running background service, I would suggest you to return START_STICKY - which tries its best to re-run the service once its destroyed due to any reasons.
The priority depends on the component type and the current app that the user is using. The highest priority have the current Activity that is displayed to the user and all foreground services. Foreground services must have a notification that cannot be dismissed. To create a foreground service you have to call startForeground(...) method from the Service itself passing the id of the notification and the Notification object itself. You can use the id if you want to update the notification later.
I recommend you to make the service bound and bind your activity to the service. This way the you can start and stop the service in your onResume and onPause methods.
The only way to increase service priority in this case is to make it a foreground service.

Categories

Resources