How to handle background services in ANDROID O? — startForeground()
Nothing makes an android developer more crazy than a new version of Android.
Google has just revealed the DP1 of the next iteration of android: Android O. There are many new exciting features and under the hood performance improvements in the newest version of android.
While others talk about what will be the name of Android O, let’s analyze this flavour of android from developer’s perspective. For android developers there are four groundbreaking changes:
- Background execution limits
- Location updates limit
- Removing of implicit broadcasts
- Notification channels
Here, in this article let’s talk about background execution limitation. Background execution limitations mainly apply to two major components:
Let’s talk about the limitations applied on services in this article.
What is the service in android?
Let’s first refresh what is the service in Android? As per the android documentation:
Serviceis an application component that can perform long-running operations in the background, and it does not provide a user interface.
So, fundamentally Service is the same thing as the activity but it doesn’t have the UI component in it. So, it doesn’t have to perform smooth animation at 60 fps. That’s why it can run perform any task for the longer period of time than the activity.
There are three types of the service:
- Started Service — A service is started when an application component (such as an activity) calls
- Bound Service — A service is bound when an application component binds to it by calling
- Scheduled Service — A service is scheduled when an API such as the
Background vs Foreground applications:
To learn background execution changes, we need to know the difference between background and foreground application first.
Rule of thumb, your application will be considered as a foreground service if any of the below three cases are true:
- Your application has currently visible activity.
- Your application has foreground service running.
- Your application is connected to another foreground app by binding the service or by consuming their content providers.
If any of the above scenarios is not true in the current instance, your application is considered to be in the background.
Why do we need to restrict the use of background services?
Whenever your applications run in the background using services, your application consumes two precious resources: 1) Memory and 2) Battery.
These two are limited resources on the mobile devices and most of the low to mid-range devices doesn’t have plenty of memory or battery inside it.
Suppose, if your application is doing some very intensive tasks in the background and using the larger amount of RAM to perform that task, then this will create the very junky user experience, especially if the user is using another resource-intensive app, such as playing a game or watching a video in foreground.
As per the documentation for the started service the best practice is,
When the operation is complete, the service should stop itself.
But, many applications have long running background services, which basically runs for the infinite time to either maintain the socket connection with the server or monitor some tasks or user activity. These services create battery drain and also they constantly consume memory.
From past couple of releases of android (Starting from Marshmallow), Google is trying very hard to increase the battery life and reduce the memory consumption used by the applications by introducing the doze mode and app standby by delaying the background execution by some amount of time if the phone is idle.
But most of the time despite of knowing the downsides of the long-running services developers still use them. (Mostly because it is easy to implement and maintain rather than using other workarounds.)
What are the limitations on services starting from Android O?
Starting from Android O, if your application is in the background (check above three conditions), your application is allowed to create and run background services for some minutes.
After some minutes passed, your application will enter in the idle stage. When your application enters in the idle stage, the system will stop all the background services just like your service calls Service.stopSelf().
And here comes the fun part…
As I discussed above, the problem of battery drain and memory consumption are mainly caused by started services. To eliminate this, Android O completely prevents the use of startService() method to start the service. If you callstartService() on Android O, you will end up getting IllegalArgumentException😲.
There are some exceptions in these scenarios when your application is whitelisted temporarily for some time window. During this period, your application can create background services freely. The application will put into temporary whitelist under below situations:
- When high priority FCM message received
- Receiving a broadcas
- Executing a PendingIntent from a notification.
How can you run background tasks?
If you are building a very large android application, there might be some genuine scenarios where you need to perform some tasks in background. Since starting a service using startService() command is not an option, we need to find out another ways to perform the tasks in background.
Scheduling your tasks using Job Scheduler API:
- JobScheduler api introduced in API21 to perform background tasks.
- This API allows you to run scheduled service and the android system will batch all the services from different applications and run them together in some particular timeframe. The reason behind this is to reduce the amount of time your phone’s CPU and radio wakes up by batching the tasks together. This will consume less battery and maintains system health.
- What if your application has minSdkVersion < 21? In this situation the official way to schedule the job is to use Firebase Job Dispatcher. Firebase Job Dispatcher is supported to all the way down upto API9.
Use foreground service
If you want some long running tasks to be performed in the background, consider using foreground services for that. None of the above background execution limitations applies to the foreground services.
This will also keep your user aware that your application is performing some background tasks by displaying the ongoing notification. This will increase transparency with your user.
Before Android O, if you want to create foreground service, you usually start a background service by calling startService(). Then after you can promote your service to the foreground service by assigning an ongoing notification using startForeground() method. But starting from Android O, you cannot use startService() anymore. So to create foreground service you have to useNotificationManager.startServiceInForeground(). This method is equivalent to creating background service and promoting it to the foreground service combine.
These limitations applied to the background service will definitely provide extended battery life and also lower RAM usage. Ultimately it will make your applications smooth and your user happy.
Should you make changes in your application code now?
Android O is still in DP1. There are 3 more developer previews to be release before the final version of Android O gets released. There might be some API changes in upcoming releases. So, right now it’s time to think the effects of these changes in your application and think about the alternative solution for them. Once developer preview 3–4 gets released, apply those changes to your applications and make your application Android O compatible.