Search code examples
androidgeolocationandroid-pendingintentbackground-serviceactivity-transition

Intent service can't be started in background


In my android app I want to detect activity change from still to walking and start tracking location, regardless of the state of the app (in background or shut down completely).

I was able to create location tracking service which works while app in background by making it a foreground service (showing notification), but I have not been able to start tracking based on activity detection.

This is fragment of code of IntentService, which supposed to start location tracking service, after receiving intent with activity transition detected:

class ActivityDetectionIntent : IntentService(TAG) {
    override fun onHandleIntent(intent: Intent?) {
        val i = Intent(this@ActivityDetectionIntent, LocationTracking::class.java)
        if (Build.VERSION.SDK_INT >= 26) {
            startForegroundService(i)
            // this followed by foregroundService call in LocationTracking service
        } else {
            startService(i)
        }
    }
    // ...
}

This is the error message I'm getting:

2019-12-04 19:57:59.797 3866-15015/? W/ActivityManager: Background start not allowed: service Intent { cmp=com.anatoliymakesapps.myapplication/.ActivityDetectionIntent (has extras) } to com.anatoliymakesapps.myapplication/.ActivityDetectionIntent from pid=-1 uid=10377 pkg=com.anatoliymakesapps.myapplication startFg?=false

I wonder if I miss something obvious, or maybe this whole approach is wrong and I need to try something else? Any piece of advice to achieve the desired result is appreciated.

I tried changing IntentService to JobIntentService but it made no difference, error looks the same.


Solution

  • Turns out intent service can not be started directly, but with help of broadcast receiver it can be achieved indirectly.

    This is what I used instead of IntentService:

    class ActivityTransitionBroadcastReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            Log.i(TAG, "got activity transition signal")
            val i = Intent(context, LocationTrackingService::class.java)
            if (Build.VERSION.SDK_INT >= 26) {
                startForegroundService(context, i)
            } else {
                context.startService(i)
            }
        }
    
        companion object {
            private val TAG = ActivityTransitionBroadcastReceiver::class.java.simpleName
        }
    
    }
    

    manifest:

            <receiver android:name=".ActivityTransitionBroadcastReceiver"  android:exported="true" />