Search code examples
javaandroidkotlinlocation

Android location Update not working when app is on background


Android 12 Location updates not working when app is on background. and work fine when app is on forground.

I also "allow all time" permission for for location. Acc to docs after this location updates start work on background. but in my case it stop updates when app is on foreground.

locationUpdatePendingIntent

    private val locationUpdatePendingIntent: PendingIntent by lazy {
    val intent = Intent(context, LocationUpdatesBroadcastReceiver::class.java)
    intent.action = LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES
    PendingIntent.getBroadcast(context, 0, intent,  PendingIntent.FLAG_MUTABLE)
}

Firstly I use Location Request. inside Automatic Workmanager

val mLocationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 0L)
    .setWaitForAccurateLocation(false)

    .build()
if (ActivityCompat.checkSelfPermission(
        context.applicationContext,
        Manifest.permission.ACCESS_FINE_LOCATION
    ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
        context,
        Manifest.permission.ACCESS_COARSE_LOCATION
    ) != PackageManager.PERMISSION_GRANTED
) {
    return Result.success();
}
fusedLocationProviderClient?.requestLocationUpdates(
    mLocationRequest,
    locationUpdatePendingIntent
)

then listen to location updates used inside Automatic Workmanager

override fun onLocationUpdate(location: Location) {
    val executor: ExecutorService = Executors.newSingleThreadExecutor()

    executor.execute {
        lastLocation = location
        updateLocation()
    }
}

Location update broadcast (in this location update)


import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.location.Location
import android.util.Log
import com.google.android.gms.location.LocationAvailability
import com.google.android.gms.location.LocationResult


class LocationUpdatesBroadcastReceiver: BroadcastReceiver() {
    private  val TAG = "LocationUpdatesBroadcas";
    override fun onReceive(context: Context?, intent: Intent?) {
        Log.d(TAG, "onReceive() context:$context, intent:$intent")

        if (intent?.action == ACTION_PROCESS_UPDATES) {

            // Checks for location availability changes.
            LocationAvailability.extractLocationAvailability(intent)?.let { locationAvailability ->
                if (!locationAvailability.isLocationAvailable) {
                    Log.d(TAG, "Location services are no longer available!")
                }
            }

            LocationResult.extractResult(intent)?.let { locationResult ->
                Log.e(TAG, "onReceive: lastLocation ${locationResult.locations.size}", )
                if(locationResult.lastLocation != null){
                    ShareLocationToAutomaticWorker.INSTANCE?.reciveLocation(locationResult.lastLocation!!)
                }

            }
        }
    }

    companion object {
        const val ACTION_PROCESS_UPDATES =
            "action." +
                    "PROCESS_UPDATES"
    }

    interface UpdatedLocation{
        fun onLocationUpdate(location: Location)
    }
}

class ShareLocationToAutomaticWorker(var updateLocation: LocationUpdatesBroadcastReceiver.UpdatedLocation){
    private  val TAG = "LocationUpdatesBroadcas"

    fun reciveLocation( location:Location){
        Log.e(TAG, "reciveLocation:--- ${location} " )
        updateLocation.onLocationUpdate(location)
    }


    companion object {
        var INSTANCE: ShareLocationToAutomaticWorker? = null

        fun getInstance(updateLocation: LocationUpdatesBroadcastReceiver.UpdatedLocation): ShareLocationToAutomaticWorker {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: ShareLocationToAutomaticWorker(
                    updateLocation )
                    .also { INSTANCE = it }
            }
        }
    }
}

Solution

  • I fixed this issue by changing "AutomaticLocationWorker" to "AutomaticLocationBackgroundService:LifecycleService()" or change worker to lifecycleService.

    private var fusedLocationProviderClient: FusedLocationProviderClient? = null

        private val locationUpdatePendingIntent: PendingIntent by lazy {
            val intent = Intent(this, LocationUpdatesBroadcastReceiver::class.java)
            intent.action = LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES
            PendingIntent.getBroadcast(this, 0, intent,  PendingIntent.FLAG_MUTABLE)
        }
    
      fusedLocationProviderClient?.requestLocationUpdates(
                mLocationRequest,
                locationUpdatePendingIntent
            )
    

    LocationUpdatesBroadcastReceiver

    
    class LocationUpdatesBroadcastReceiver: BroadcastReceiver() {
        private  val TAG = "LocationUpdatesBroadcas";
        override fun onReceive(context: Context?, intent: Intent?) {
            Log.d(TAG, "onReceive() context:$context, intent:$intent")
    
            if (intent?.action == ACTION_PROCESS_UPDATES) {
    
                // Checks for location availability changes.
                LocationAvailability.extractLocationAvailability(intent)?.let { locationAvailability ->
                    if (!locationAvailability.isLocationAvailable) {
                        Log.d(TAG, "Location services are no longer available!")
                    }
                }
    
                LocationResult.extractResult(intent)?.let { locationResult ->
                    Log.e(TAG, "onReceive: lastLocation ${locationResult.locations.size}", )
                    if(locationResult.lastLocation != null){
                        ShareLocationToAutomaticWorker.INSTANCE?.reciveLocation(locationResult.lastLocation!!)
                    }
    
                }
            }
        }
    
        companion object {
            const val ACTION_PROCESS_UPDATES =
                "com.commuteoptm.bcos.background_services.action." +
                        "PROCESS_UPDATES"
        }
    
        interface UpdatedLocation{
            fun onLocationUpdate(location: Location)
        }
    }
    

    ShareLocationToAutomaticWorker

    class ShareLocationToAutomaticWorker(var updateLocation: LocationUpdatesBroadcastReceiver.UpdatedLocation){
        private  val TAG = "LocationUpdatesBroadcas"
    
        fun reciveLocation( location:Location){
            Log.e(TAG, "reciveLocation:--- ${location} " )
            updateLocation.onLocationUpdate(location)
        }
    
    
        companion object {
            var INSTANCE: ShareLocationToAutomaticWorker? = null
    
            fun getInstance(updateLocation: LocationUpdatesBroadcastReceiver.UpdatedLocation): ShareLocationToAutomaticWorker {
                return INSTANCE ?: synchronized(this) {
                    INSTANCE ?: ShareLocationToAutomaticWorker(
                        updateLocation )
                        .also { INSTANCE = it }
                }
            }
        }
    }