Peter Chikov
Peter Chikov

Reputation: 151

Get current location in Android Development

I have a service worker that runs every 10 minutes and needs to get the current latitude and longitude every time it runs and I've been using the following code:

private var fusedLocationClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(applicationContext)

override fun doWork(): Result {
val priority = Priority.PRIORITY_HIGH_ACCURACY
val cancellationTokenSource = CancellationTokenSource()

fusedLocationClient.getCurrentLocation(priority, cancellationTokenSource.token)
            .addOnSuccessListener { location ->
                Log.e("Location", "location is found: $location")
                curLat = location.latitude
                curLong = location.longitude
            }
            .addOnFailureListener { exception ->
                Log.e("Location", "Oops location failed with exception: $exception")
            }
}

Unfortunately, location is always null.

Per https://stackoverflow.com/a/72038138/4696054 and several other answers: "If the location subsystem wasn't already on, it doesn't know what the location was, so it returns null. If you want to ensure that you don't get null, request updates."

This "request updates" part is confusing to me. I just need to get the location once when the service starts.

How am I able to do that and where do I initialize the location service for the update (other answers I found have been deprecated)? Service worker does not have "OnCreate" method where I can initialize the location service for https://developer.android.com/develop/sensors-and-location/location/request-updates and LocationRequest has been deprecated (at least Create () is deprecated).

Granted Permissions are:

android.permission.ACCESS_COARSE_LOCATION and android.permission.ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION

EDIT: Per @CommonWare I tried:

val currentBuilder = CurrentLocationRequest.Builder().setDurationMillis(30000)
currentLocationRequest = currentBuilder.build()
fusedLocationClient.getCurrentLocation(currentLocationRequest, null)
            .addOnSuccessListener { location ->
                Log.e("Location", "location is found: $location")
                curLat = location.latitude
                curLong = location.longitude
            }
            .addOnFailureListener { exception ->
                Log.e("Location", "Oops location failed with exception: $exception")
            }

Unfortunately, location is still null

Upvotes: 0

Views: 1870

Answers (3)

Nadh
Nadh

Reputation: 72

This worked for me

Mark user

    private fun markUser(googleMap: GoogleMap) {

      if(!checkLocationPermission()){
        requestLocationPermission()
      }

      if (ActivityCompat.checkSelfPermission(
            requireContext(),
            Manifest.permission.ACCESS_FINE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
            requireContext(),
            Manifest.permission.ACCESS_COARSE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
      ) {
        fusedLocationClient.lastLocation
            .addOnSuccessListener { location: Location? ->
                if (location != null) {
                    val latitude = location.latitude
                    val longitude = location.longitude
                    val userIcon =
                        BitmapDescriptorFactory.fromResource(android.R.drawable.btn_star_big_on)
                    val userLocation = LatLng(latitude, longitude)
                    googleMap.addMarker(
                        MarkerOptions()
                            .position(userLocation)
                            .title("You")
                            .icon(userIcon)
                    )
                }
            }
       }
   }

Permission

private fun checkLocationPermission(): Boolean {
    val permission = Manifest.permission.ACCESS_FINE_LOCATION
    return ContextCompat.checkSelfPermission(
        requireContext(),
        permission
    ) == PackageManager.PERMISSION_GRANTED
}

private fun requestLocationPermission() {
    val permission = Manifest.permission.ACCESS_FINE_LOCATION
    ActivityCompat.requestPermissions(requireActivity(), arrayOf(permission), REQUEST_LOCATION_PERMISSION)
}

@Deprecated("Deprecated in Java")
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    when (requestCode) {
        REQUEST_LOCATION_PERMISSION -> {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                shareCurrentLocation()
            }
        }
    }
}

When testing in Android Studio, default locations may be marked on your machine. Therefore, ensure to conduct tests on a mobile device.

Upvotes: 0

Muhannad Fakhouri
Muhannad Fakhouri

Reputation: 1554

you need to request location updates try the following for instance


    val fusedLocationProviderClient =
        LocationServices.getFusedLocationProviderClient(activity)
    val locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            val location = locationResult.lastLocation
            if (location != null) {
                val latitude = location.latitude
                val longitude = location.longitude

                // Use latitude and longitude for your purposes
                Log.d("Location", "Latitude: $latitude, Longitude: $longitude")

                // Remove location updates after receiving one
                fusedLocationProviderClient.removeLocationUpdates(this)
            } else {
                Log.w("Location", "Failed to get location update")
            }
        }
    }

    if (ContextCompat.checkSelfPermission(
            activity,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        // Request permissions if not granted
        val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
        activity.requestPermissions(permissions, LOCATION_PERMISSION_CODE)
        return
    }

    val locationRequest =
        LocationRequest.Builder(0L).setPriority(Priority.PRIORITY_HIGH_ACCURACY).build()

    fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, null)

Upvotes: 0

Jayanta Sarkar
Jayanta Sarkar

Reputation: 644

So here's how you can get your current location. I am skipping the permission part as you can do that yourself.

private fun isLocationEnabled(): Boolean {
        val locationManager: LocationManager =
            getSystemService(Context.LOCATION_SERVICE) as LocationManager
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
            LocationManager.NETWORK_PROVIDER
        )
    }
 private fun getLastLocation() {
        if (isLocationEnabled()) {
           fusedLocationClient.lastLocation.addOnCompleteListener(this) { task ->
                val location: Location? = task.result
                if (location != null) {
                    //use the location latitude and logitude as per your use.
                    val latitude = location.latitude
                    val longitude = location.longitude
                }
            }
        }

Upvotes: 1

Related Questions