Working with JobIntentService in Android

JobIntentService is the modern way of using the background service to get our task done. The IntentService does not work well with Oreo devices and above. That is it made our application crash in the Oreo devices. To overcome this problem android introduced JobIntentService that works well in all the devices.

Properties of the JobIntentService

  • Min Support Version. It works in starting from API 14 onwards. So without any hesitation, you can use the JobIntentService for all your target application, That why it is known as a modern way to run the background service.
  • When running on Android Oreo devices the JobIntentService uses the JobScheduler. This will handle the Wake Locks for you. On any device pre Android Oreo, the JobIntentService will set up Wake Locks through the PowerManager, so make sure you require the android.permission.WAKE_LOCK permission in your manifest.
  • When running on anything less than Android Oreo the service will start almost instantly. On Android Oreo it will be subject to JobScheduler policies, in other words it will not run while the device is dozing and may get delayed more than a usual service when the system is under heavy load.
  • On pre Android Oreo the service can run indefinitely but on Android Oreo it will adhere to the usual JobService execution type limits. At which point it will stop (not the process) and continue execution at a later time.

Steps to implement JobIntentService

  1. Create a subclass of JobIntentService
  2. Override onHandleWork() method
  3. Expose enqueueWork() method
  4. Write code in Manifest file. For Pre-Oreo devices add in Manifest WAKE-LOCK permission. For Oreo device or above allow JobIntentService to user JobScheduler API. Declare android.premssion.BIND_JOB_SERVICE.

Add WAKELOCK Permission to Manifest.xml

<uses-permission android:name="android.permission.WAKE_LOCK" />

Add JobIntentService class to Manifest.xml

<service
    android:name=".MyJobIntentService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="true"/>

Create a new file with name is MyJobIntentService which extends the JobIntentServcie.

class MyJobIntentService : JobIntentService() {
    override fun onHandleWork(intent: Intent) {
        val maxCount = intent.getIntExtra("maxCountValue", -1)
        for (i in 0 until maxCount) {
            Log.d(TAG, "onHandleWork: The number is: $i")
            try {
                Thread.sleep(1000)
            } catch (e: InterruptedException) {
                e.printStackTrace()
            }

        }
    }

    companion object {
        val JOB_ID = 2
        val TAG = "TAG"

        fun enqueueWork(context: Context, intent: Intent) {
            enqueueWork(context, MyJobIntentService::class.java, JOB_ID, intent)
        }
    }

}

Run from Activity

val intent = Intent(this, MyJobIntentService::class.java)
intent.putExtra("maxCountValue", 10)
MyJobIntentService.enqueueWork(this, intent)

Run from Broadcast

class BootCompleteReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            val intent = Intent(this, MyJobIntentService::class.java)
            intent.putExtra("maxCountValue", 10)
            MyJobIntentService.enqueueWork(this, intent)
        }
    }
}

Registred the Receiver inside the Manifest file.

<receiver android:name=".BootCompleteReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>