Search code examples
androidkotlinandroid-intentservicejobintentserviceandroid-11

IntentService is deprecated, how do I replace it with JobIntentService?


Following FetchAddressIntentService implementation with IntentService (in kotlin):

class FetchAddressIntentService  //Constructor of this service
    : IntentService(INTENTTAG) {
    //Receiver where results are forwarded from this service
    protected var resultReceiver: ResultReceiver? = null

    private val TAG by lazy { this::class.java.simpleName }

    //Intent Service handler
    override fun onHandleIntent(intent: Intent?) { //Errormessages
        var errorMessage = ""
        if (intent != null) {
            resultReceiver =
                intent.getParcelableExtra(RECEIVER)
        }
        //Checks if receiver was properly registered
        if (resultReceiver == null) {
            Log.wtf(
                TAG,
                "No reciever received. There is nowhere to send the results !!"
            )
            return
        }
        //Get the location passed to this service through an extra.
        var location: Location? = null
        if (intent != null) {
            location =
                intent.getParcelableExtra(LOCATION_DATA_EXTRA)
        }
        //Make sure the location is really sent
        if (location == null) {
            errorMessage = getString(R.string.gis_error_no_location_data_provided)
            Log.wtf(TAG, errorMessage)
            deliverResultToReceiver(FAILURE_RESULT, errorMessage)
            return
        }
        //Setting locale
        val geocoder = Geocoder(this, Locale.ROOT)
        //Address found
        var addresses: List<Address>? = null
        try {
            addresses = geocoder.getFromLocation(location.latitude, location.longitude, 1)
            Log.i(TAG,"rec: address = ${addresses[0]}")
        } catch (ioException: IOException) { //Catches network or i/o problems
            errorMessage = getString(R.string.gis_error_service_not_available)
            Log.e(TAG, errorMessage, ioException)
        } catch (illegalArgumentException: IllegalArgumentException) { //Error in latitude or longitude data
            errorMessage = getString(R.string.gis_error_invalid_lat_long_used)
            Log.e(
                TAG,
                errorMessage + ". Latitude = " + location.latitude +
                        ", Longitude = " + location.longitude,
                illegalArgumentException
            )
        }
        //Handles cases where no addresses where found
        if (addresses == null || addresses.isEmpty()) {
            if (errorMessage.isEmpty()) {
                errorMessage = getString(R.string.gis_error_no_address_found)
                Log.e(TAG, errorMessage)
            }
            deliverResultToReceiver(FAILURE_RESULT, errorMessage)
        } else {
            val address = addresses[0]
            //deliverAddressToReceiver(SUCCESS_RESULT, address)
            deliverAddressToReceiver2(SUCCESS_ADDRESS,address)
        }
    }

    private fun deliverAddressToReceiver2(
        resultCode: Int,
        address: Address
    ){
        val bundle = Bundle()
        bundle.putParcelable("address",address)
        resultReceiver?.send(resultCode,bundle)
    }

    private fun deliverResultToReceiver(resultCode: Int, message: String) {
        val bundle = Bundle()
        bundle.putString(RESULT_DATA_KEY, message)
        resultReceiver!!.send(resultCode, bundle)
    }

    companion object {
        private const val INTENTTAG = "FetchAddressIS"
    }
}

Do anyone have a suggestion how I can replace IntentService with JobIntentService in a good way ?

IntentService is deprecated in Android-R / Android-11.

I have tried following some posts on this, but no one is directing the correct path how to change the usability of the IntentService call to JobIntentService call in the way this AddressFetchIntentService is using IntentService.

RG


Solution

  • class FetchAddressIntentService : JobIntentService() {
    
        // This method is called when service starts instead of onHandleIntent
        override fun onHandleWork(intent: Intent) {
            onHandleIntent(intent)
        }
    
        // remove override and make onHandleIntent private.
       private fun onHandleIntent(intent: Intent?) {}
    
        // convenient method for starting the service.
        companion object {
            fun enqueueWork(context: Context, intent: Intent) {
                enqueueWork(context, FetchAddressIntentService::class.java, 1, intent)
            }
        }
    }
    

    You can start the service as

        val intent = Intent(this, FetchAddressIntentService::class.java)
        FetchAddressIntentService.enqueueWork(this, intent)
    

    Important:

    You need to add permissions to manifest.

    <uses-permission android:name="android.permission.WAKE_LOCK" /> // needed for pre-oreo devices

    also

    <service
        android:name=".FetchAddressIntentService"
        android:permission="android.permission.BIND_JOB_SERVICE" // needed for oreo and above
        android:exported="true"/>
    

    Read more here


    ADDED 2020.06.02 19:20 GMT By Roar Grønmo

    I changed my code to:

    class FetchAddressJobIntentService:JobIntentService()
    {
        private val TAG by lazy { this::class.java.simpleName }
    
        protected var resultReceiver: ResultReceiver? = null
    
        /*
        override fun onHandleWork(intent: Intent) {
            onHandleIntent(intent)
        }*/
    
        override fun onHandleWork(intent: Intent) { //Errormessages
            var errorMessage = ""
    
            resultReceiver = intent.getParcelableExtra(RECEIVER)
    
            //Checks if receiver was properly registered
            if (resultReceiver == null) {
                Log.wtf(
                    TAG,
                    "No reciever received. There is nowhere to send the results !!"
                )
                return
            }
            //Get the location passed to this service through an extra.
            var location: Location? = null
    
            location = intent.getParcelableExtra(LOCATION_DATA_EXTRA)
    
            //Make sure the location is really sent
            if (location == null) {
                errorMessage = getString(R.string.gis_error_no_location_data_provided)
                Log.wtf(TAG, errorMessage)
                deliverResultToReceiver(FAILURE_RESULT, errorMessage)
                return
            }
            //Setting locale
            val geocoder = Geocoder(this, Locale.ROOT)
            //Address found
            var addresses: List<Address>? = null
            try {
                addresses = geocoder.getFromLocation(location.latitude, location.longitude, 1)
                Log.i(TAG,"rec: address = ${addresses[0]}")
            } catch (ioException: IOException) { //Catches network or i/o problems
                errorMessage = getString(R.string.gis_error_service_not_available)
                Log.e(TAG, errorMessage, ioException)
            } catch (illegalArgumentException: IllegalArgumentException) { //Error in latitude or longitude data
                errorMessage = getString(R.string.gis_error_invalid_lat_long_used)
                Log.e(
                    TAG,
                    errorMessage + ". Latitude = " + location.latitude +
                            ", Longitude = " + location.longitude,
                    illegalArgumentException
                )
            }
            //Handles cases where no addresses where found
            if (addresses == null || addresses.isEmpty()) {
                if (errorMessage.isEmpty()) {
                    errorMessage = getString(R.string.gis_error_no_address_found)
                    Log.e(TAG, errorMessage)
                }
                deliverResultToReceiver(FAILURE_RESULT, errorMessage)
            } else {
                val address = addresses[0]
                //deliverAddressToReceiver(SUCCESS_RESULT, address)
                deliverAddressToReceiver2(SUCCESS_ADDRESS,address)
            }
        }
    
        private fun deliverAddressToReceiver2(
            resultCode: Int,
            address: Address
        ){
            val bundle = Bundle()
            bundle.putParcelable("address",address)
            resultReceiver?.send(resultCode,bundle)
        }
    
        private fun deliverResultToReceiver(resultCode: Int, message: String) {
            val bundle = Bundle()
            bundle.putString(RESULT_DATA_KEY, message)
            resultReceiver!!.send(resultCode, bundle)
        }
    
    
    
        companion object{
            fun enqueueWork(context: Context, intent: Intent){
                enqueueWork(context,FetchAddressJobIntentService::class.java, 1, intent)
            }
        }
    
    }