In the following months new changes are coming for all Android developers. Google is going to ensure the best performance on all applications in Google Play, so for that purpose is going to force Android developers target their apps to Android Oreo.

During Google I/0 2018 it was announced that from August 2018 all new apps, that developers upload to Google Play, have to be targeting Android Oreo (8.0). Starting from November 2018, the requirement will affect to updates of existing apps as well.

The changes we have to take in mind about this migration are:

Services — Background limitations BroadcastReceivers Notifications RunTime Permissions Alarms Firebase Cloud Messaging (deadline April 2019)

1. SERVICES — BACKGROUND LIMITATIONS

This is not a new issue. It was presented when Android Oreo was released, but due to the low adoption rate, many of Android developers are not yet targeting to Android Oreo. (around 5% in May 2018 — https://developer.android.com/about/dashboards/)

You can get more details about the motivation behind these restrictions in the following link:

The first change that we have to face is that we are NOT allowed to call “startService()” to make some work in the background (location updates, sync data…) if our app is not in the foreground (if our app is in the foreground we can call the method “startService()”). In this case when we call startService an exception IllegalStateException will be thrown.

Instead, we will use “startForegroundService()”. We have 5 seconds approximately to show a notification that tells the user that we are doing some operation in the background. These notification will be active while our service is working and will disappear when the service ends.

Notification to show user indicating we are working in the background

So in our service the first thing that we have to do is show the notification:

Another point. If we need to launch a service in the background while the application is not in the foreground (ex: after receiving a push notification), the system will show something like this:

And like in the other scenario, the notification will disappear when the work is done.

✋ IMPORTANT ✋

Hide notification as soon as possible 👀

If we want our notification to be hidden as soon as possible we have to call “stopForeground(true);” when the services ends. Making this call, when the services ends the notification will disappear. If we don’t do that the notification will remain in the statusBar for a period of time until the system makes it disappear.

2. Avoid notification sounds 🔊

Another issue that we have to keep in mind is that notifications make sound, so depending on the priority that we have assigned to our notification, when the service is launched we could be surprised with the notification sound. So this is not the behavior we want, to solve it we have to assign IMPORTANCE_LOW priority to our notification. We can not assign lower priority, if we do that the system makes crash uor app when launch the service.

val channel = NotificationChannel(channelId, BuildConfig.NOTIFICATION_CHANNEL_SILENT_NAME, NotificationManager.IMPORTANCE_LOW)

We recommend to create a notification channel only for silent notifications, in this way we avoid to alert users with sounds and the other notifications will continue to behave with normal operation.

You can check all the priorities for a notification here.

With all these limitations, what Google wants is to ensure that developers before launching a service in the background study whether it is the best way to do it. In this way you will get a better user experience and better performance of our device.

INTENT SERVICES → JOB INTENT SERVICES

Until now when we wanted to launch an intent service for running some long operation in the background, we called “startService()” but from now, how we say before, it is not more allowed.

So the changes we have to do are easy. All our IntentServices that look like this:

Now we have to extend from JobIntentService. The JobIntentService are similar to a Service, however it enqueues the work into the JobScheduler on compatible Android targets.

Once we have the JobIntentService, to execute this operation in the background we have to make something like this:

And don’t forget to update your AndroidManifest.xml indicating that this service is a bind job service.

Next posts try to understand other changes that we have to make to target Android Oreo in our apps.

I hope this post is useful for you and if you detect something wrong don’t hesitate to tell us.

INTERESTING LINKS

https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c

https://android.jlelse.eu/keep-those-background-services-working-when-targeting-android-oreo-sdk-26-cbf6cc2bdb7f

Extra: This video shows in a brief way all the changes that we have to accomplish in the next few months to target Android Oreo and above.