2

I am trying to access the location information of my Android phone using an app and I can not appear to get the current location. My code is as follows:

fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity())

val location_button = view.findViewById<ImageButton>(R.id.get_location)
location_button.setOnClickListener {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (ContextCompat.checkSelfPermission(requireActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED || ContextCompat.checkSelfPermission(requireActivity(), android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_DENIED) {
            val permission = arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION)
            requestPermissions(permission, LOC_PERMISSION_CODE)
        }
        else {
            //permission already granted
            fusedLocationClient.lastLocation
                .addOnSuccessListener { location ->
                    // Got last known location. In some rare situations this can be null.
                    val latitude = location?.latitude
                    val longitude = location?.longitude
                    println(latitude)
                    println(longitude)
                }
                .addOnFailureListener {
                    Toast.makeText(requireActivity(), "Failed on getting current location",
                        Toast.LENGTH_SHORT).show()
                }
        }
    }
    else {
        fusedLocationClient.lastLocation
            .addOnSuccessListener { location : Location? ->
                // Got last known location. In some rare situations this can be null.
                println(location)
            }
    }

Upon the first run, I successfully get prompted to grant location access and I do so. Then it calls for the lastLocation which always equals null. If I run the app again, I will get sent to the first else block where I print out latitude and longitude but they both always print null even though I have successfully granted location access, and called for the last location.

I was beginning to think maybe last location does not work if a location has never been saved and I see there is a function from the FusedLocationProviderClient class named "getCurrentLocation()" but I can not figure out how to call it. Am I missing something?

Tyler
  • 127
  • 3
  • 11

2 Answers2

3

as Gabe Sechan suggested you have to call for new location if you don't want your location to be null or require a fresh location everytime.

you can do it using getCurrentLocation() method which takes priority and a cancellation token.

val priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
val cancellationTokenSource = CancellationTokenSource()

fusedLocationClient.getCurrentLocation(priority, cancellationTokenSource.token)
            .addOnSuccessListener { location ->
                Log.d("Location", "location is found: $location")
            }
            .addOnFailureListener { exception ->
                Log.d("Location", "Oops location failed with exception: $exception")
            }

you can change the priority based on your requirement as of now i have used PRIORITY_BALANCED_POWER_ACCURACY as it will search location using wifi and GPS to find location if you required with higher accuracy you can use PRIORITY_HIGH_ACCURACY

and we provide cancellation token as if in future we're not required location for e.g. Activity has been closed by user so we will cancel request using cancellationTokenSoure.cancel()

Bhavin
  • 577
  • 6
  • 11
  • I have tried this method and I get an error in Android Studio that getCurrentLocation is an unresolved reference, any idea why that would be? – Tyler Apr 29 '22 at 03:44
  • @Tyler can you check for location service dependency named `com.google.android.gms:play-services-location:*.*.*` and update it if required. – Bhavin Apr 29 '22 at 04:20
  • 1
    Sounds good I will check that and update if needed. – Tyler Apr 29 '22 at 13:43
  • Bhavin, I updated the dependency and now the getCurrentLocation method is valid. I execute the code but the location returned is always null still. I have location services turned on the the proper permissions set. I am trying to call this function from a Fragment. Is there more to get this thing working? – Tyler May 01 '22 at 14:38
  • @Tyler can you provide your sample code if possible that how you ask for the location. as this method will generate new location if possible and returned it. – Bhavin May 02 '22 at 08:36
  • @Bhavin kindly use `const val priority = Priority.PRIORITY_HIGH_ACCURACY ` in place of `val priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY` since it's depreciated. – RocqJones Nov 30 '22 at 07:47
1

LastKnownLocation returning null is the norm. 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.

LastKnonLocation should only be used as a mild optimization if you really know what you're doing. Otherwise, don't call it.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127