Write your Android app to run in background mode as a service

September 12, 2020

In some use cases, you may encounter a problem when your users put your app in the background mode or screen lock state, then your app functionality would be lost after several minutes. This would not be a good user experience, which may cause a Bluetooth device disconnected from your app or data sync to server in the background got interrupted. Users would then complain about the connectivity and stability of your app.

To solve this problem, first, you need to understand a bit of the android app Activity lifecycle. When your user got distracted and open Facebook app in the foreground instead of your app, your app’s activity is finished and the onDestroy() would be triggered. This is good for the android system as it would free up unused memory as well as better battery management. However, this may not be good for your app since it got killed and your states and functionality are lost.

Next step, you need to refactor your app to separate the background functionality, such as Bluetooth connectivity, into a service. A Service is an application component that can perform long-running operations in the background, independent from the user interface. Here is an example of a service code:

import android.app.Service

class MyService : Service() {

    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    override fun onCreate() {
      // move your service logic here
    }

    override fun onDestroy() {
      // clean up your service logic here
    }

}

To use this service, you also need to define it in your AndroidManifest.xml, here is an example (replace the name with your service package name):

<application>
    ...
    <service android:enabled="true" android:name="com.victorleungtw.myapp.services.MyService"></service>

</application>

One more thing, to trigger the start on this service in your activity, such as Activity onCreate, add this line:

startService(Intent(this, MyService::class.java))

Also at the place where you want to stop the service, add this line:

stopService(Intent(this, BleService::class.java))

After this change, your app is better structured, but it’s not yet able to keep running in background mode forever. To do so, inside your service, you also need to add two more methods:

class MyService : Service() {

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        val channelId =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    createNotificationChannel("my_service", "My Background Service")
                } else {
                    // If earlier version channel ID is not used
                    ""
                }

        val notification: Notification = Notification.Builder(this, channelId)
                .setContentTitle("title")
                .setContentText("text")
                .build()
        startForeground(2001, notification)

        return START_STICKY
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(channelId: String, channelName: String): String{
        val chan = NotificationChannel(channelId,
                channelName, NotificationManager.IMPORTANCE_NONE)
        chan.lightColor = Color.BLUE
        chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
        val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        service.createNotificationChannel(chan)
        return channelId
    }

}

What is happening here is that a notification is created so that your user got notify when the app still keeps running in the background. It would look something like this:

0  YTEpHMXge2V2kCry

That’s is. Now your user can multi-task, while reading Facebook app in the foreground, while keeping your app running in the background, connect with Bluetooth, sync user data or playing music etc depending on your app features.

Originally published at https://victorleungtw.com on September 12, 2020.


Written by Victor Leung who is a keen traveller to see every country in the world, passionate about cutting edge technologies. Follow me on Twitter