Get user's current location in Jetpack Compose Android

Viewed 48

Intention: I am trying to get user's current location after user grants (coarse/fine)location permission. I am using jetpack compose accompanist lib to manager permission.

So when user grants the permission, am using getCurrentLocation of FusedLocationProviderClient to get the location object, and fetching lat lang from it.

Problem: In the below code block, Logcat logs: Coordinates[0.0,0.0]

class LocationManager @Inject constructor(
    private val fusedLocation: FusedLocationProviderClient
) {

    @SuppressLint("MissingPermission")
    @Composable
    @ExperimentalPermissionsApi
    fun getLatLang(context: Context): Coordinates {
        val coordinates = Coordinates(0.0, 0.0)

        /**
         * Checking and requesting permission. If granted it will fetch current lat lang,
         * else it will request for permission.
         * If denied, will show popup to open app settings and grant location permission.
         */
        LocationPermissionManager.RequestPermission(
            actionPermissionGranted = {
                fusedLocation.getCurrentLocation(LocationRequest.PRIORITY_HIGH_ACCURACY, null)
                    .addOnSuccessListener { location ->
                        if (location != null) {
                            coordinates.lat = location.latitude
                            coordinates.long = location.longitude
                        }
                    }
            },
            actionPermissionDenied = { context.openAppSystemSettings() }
        )

        return coordinates
    }
}


data class Coordinates(var lat: Double, var long: Double)

Consuming LocationManager below:

@ExperimentalPermissionsApi
@Composable
fun AirQualityLayout(locationManager: LocationManager) {
    val context: Context = LocalContext.current

    val coordinates: Coordinates = locationManager.getLatLang(context = context)

    if (coordinates.lat != 0.0 && coordinates.long != 0.0) {
        Timber.d("Current location: $coordinates")
        ShowUI()
    }
}

Expecting suggestions/help what I am doing wrong here.

1 Answers

Do you have your manifest right? (Access_fine_location and access_coarse_location

This is a class i made sometime ago:

class LocationLiveData(var context: Context): LiveData<LocationDetails>() {

    //add dependency implementation "com.google.android.gms:play-services-maps:18.0.2"
    private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)


    override fun onActive() {
        super.onActive()


    
        if (ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) { // alse geen permissie hebben just return, anders voer functie location uit

            return
        }
        fusedLocationClient.lastLocation.addOnSuccessListener {
            location -> location.also {
                setLocationData(it)


        }

        }
    }

      internal fun startLocationUpdates() {

        if (ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            return
        }
        fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())

    }

    private fun setLocationData(location: Location?) {
      
        location?.let { it ->
            //value is observed in LiveData
            value = LocationDetails(
                longitude = it.longitude.toString(),
                lattitude = it.latitude.toString()
            )

        }
        println("value $value")


    }


    override fun onInactive() {
        super.onInactive()
        fusedLocationClient.removeLocationUpdates(locationCallback)
    }

    private val locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            super.onLocationResult(locationResult)
            println("we have a new location result")
            locationResult ?: return //als er een result is dan prima, zo niet dan just return (elvis operator)
            for (location in locationResult.locations) {
                setLocationData(location = location)

            }
        }
    }

    companion object {

        val ONE_MINUTE: Long = 1000
        @RequiresApi(Build.VERSION_CODES.S)
        val locationRequest : com.google.android.gms.location.LocationRequest = com.google.android.gms.location.LocationRequest.create().apply {
            interval = ONE_MINUTE
            fastestInterval = ONE_MINUTE/4
            priority = LocationRequest.QUALITY_HIGH_ACCURACY
        }


    }

}
Related