Open In App

How to Get Current Location in Android?

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

As a developer when you work on locations in Android then you always have some doubts about selecting the best and efficient approach for your requirement. So in this article, we are going to discuss how to get the user’s current location in Android. There are two ways to get the current location of any Android device:

  1. Android’s Location Manager API
  2. Fused Location Provider: Google Play Services Location APIs

Question: Which one is efficient and why?

Answer: Fused Location Provider because it optimizes the device’s use of battery power.

Before moving any of the above methods we will have to take location permission.

Taking Location Permission

Step 1: Define uses permissions for location access in the manifest file

<!– To request foreground location access, declare one of these permissions. –>

<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION” />

<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION” />

<!– Required only when requesting background location access on Android 10 (API level 29) –>

<uses-permission android:name=”android.permission.ACCESS_BACKGROUND_LOCATION” />

Note:

In order to receive location updates from NETWORK_PROVIDER or GPS_PROVIDER, you must request the user’s permission by declaring either the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission, respectively, in your Android manifest file. Without these permissions, your application will fail at runtime when requesting location updates.

If you are using both NETWORK_PROVIDER and GPS_PROVIDER, then you need to request only the ACCESS_FINE_LOCATION permission, because it includes permission for both providers. Permission for ACCESS_COARSE_LOCATION allows access only to NETWORK_PROVIDER.

Step 2: Define uses permission for internet access because we are going to use Internet Provider.

<uses-permission android:name=”android.permission.INTERNET”/>

Step 3: Write a function for checking that location permission is granted or not. If permission is not granted then ask for the permissions in run time.

Kotlin




private fun isLocationPermissionGranted(): Boolean {
    return if (ActivityCompat.checkSelfPermission(
            this,
            android.Manifest.permission.ACCESS_COARSE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
            this,
            android.Manifest.permission.ACCESS_FINE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(
                android.Manifest.permission.ACCESS_FINE_LOCATION,
                android.Manifest.permission.ACCESS_COARSE_LOCATION
            ),
            requestcode
        )
        false
    } else {
        true
    }
}


Now after handling location permissions, we are going to learn how can we get the location in android.

First Method: By Android’s Location Manager API

We assume that the user has been granted Location Permission. If not then ask first.

Step 1: Creating an instance of LocationManager in the context of LOCATION_SERVICE.

Kotlin




private var currentLocation: Location? = null
lateinit var locationManager: LocationManager
locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager


Step 2: Check that if the GPS and Network are available or not and if both are available then we use one with greater accuracy.

Kotlin




val hasGps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
//------------------------------------------------------//
val hasNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)


Step 3: Creating an instance of LocationListener (package: android.location) for both(GPS and Network).

Kotlin




val gpsLocationListener: LocationListener = object : LocationListener {
    override fun onLocationChanged(location: Location) {
        locationByGps= location
    }
  
    override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
    override fun onProviderEnabled(provider: String) {}
    override fun onProviderDisabled(provider: String) {}
}
//------------------------------------------------------//
val networkLocationListener: LocationListener = object : LocationListener {
    override fun onLocationChanged(location: Location) {
        locationByNetwork= location
    }
  
    override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
    override fun onProviderEnabled(provider: String) {}
    override fun onProviderDisabled(provider: String) {}
}


Step 4: If any of the GPS or Network providers is enabled then we will request a current location update from the LocationManager with LocationListener.

Kotlin




if (hasGps) {
    locationManager.requestLocationUpdates(
        LocationManager.GPS_PROVIDER,
        5000,
        0F,
        gpsLocationListener
    )
}
//------------------------------------------------------//
if (hasNetwork) {
    locationManager.requestLocationUpdates(
        LocationManager.NETWORK_PROVIDER,
        5000,
        0F,
        networkLocationListener
    )
}


Step 5: Now we check which provider has given us the more accurate location and then we will use that location as per our requirement.

Kotlin




val lastKnownLocationByGps =
  locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
lastKnownLocationByGps?.let {
    locationByGps = lastKnownLocationByGps
}
//------------------------------------------------------//
val lastKnownLocationByNetwork =
  locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
lastKnownLocationByNetwork?.let {
    locationByNetwork = lastKnownLocationByNetwork
}
//------------------------------------------------------//
if (locationByGps != null && locationByNetwork != null) {
    if (locationByGps.accuracy > locationByNetwork!!.accuracy) {
        currentLocation = locationByGps
        latitude = currentLocation.latitude
        longitude = currentLocation.longitude
        // use latitude and longitude as per your need
    } else {
        currentLocation = locationByNetwork
        latitude = currentLocation.latitude
        longitude = currentLocation.longitude
        // use latitude and longitude as per your need
    }
}


Now after learning how can we get the location in android by Location Manager API, we are moving to the second method Fused Location Provider (Google Play Services Location APIs).

Second Method: By Fused Location Provider

We assume that the user has been granted Location Permission. If not then ask first. Fused Location Provider is the Google Play services location APIs. It provides a simple API for getting locations with high, medium, and low accuracy. It also optimizes the device’s use of battery power. So we should prefer this method.

Step 1: Declare variables of FusedLocationProviderClient, LocationRequest, LocationCallback and Location.

Kotlin




// FusedLocationProviderClient - Main class for receiving location updates.
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
  
// LocationRequest - Requirements for the location updates, i.e.,
// how often you should receive updates, the priority, etc.
private lateinit var locationRequest: LocationRequest
  
// LocationCallback - Called when FusedLocationProviderClient
// has a new Location
private lateinit var locationCallback: LocationCallback
  
// This will store current location info
private var currentLocation: Location? = null


Step 2: Initialize fusedLocationProviderClient.

Kotlin




fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)


Step 3: Initialize locationRequest.

Kotlin




locationRequest = LocationRequest().apply {
    // Sets the desired interval for
      // active location updates. 
      // This interval is inexact.
    interval = TimeUnit.SECONDS.toMillis(60)
  
    // Sets the fastest rate for active location updates. 
     // This interval is exact, and your application will never
      // receive updates more frequently than this value
    fastestInterval = TimeUnit.SECONDS.toMillis(30)
  
    // Sets the maximum time when batched location 
      // updates are delivered. Updates may be
      // delivered sooner than this interval
    maxWaitTime = TimeUnit.MINUTES.toMillis(2)
  
    priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}


Step 4: Initialize locationCallback.

Kotlin




locationCallback = object : LocationCallback() {
    override fun onLocationResult(locationResult: LocationResult?) {
        super.onLocationResult(locationResult)
        locationResult?.lastLocation?.let {
            currentLocation = locationByGps
            latitude = currentLocation.latitude
            longitude = currentLocation.longitude
            // use latitude and longitude as per your need
        } ?: {
            Log.d(TAG, "Location information isn't available.")
        }
    }
}


Step 5: Now that you initialized everything, you need to let the FusedLocationProviderClient know that you want to receive updates. So Subscribe to location changes.

Kotlin




fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())


Step 6: When the app no longer needs access to location information, it’s important to unsubscribe from location updates.

Kotlin




val removeTask = fusedLocationProviderClient.removeLocationUpdates(locationCallback)
removeTask.addOnCompleteListener { task ->
   if (task.isSuccessful) {
       Log.d(TAG, "Location Callback removed.")
   } else {
       Log.d(TAG, "Failed to remove Location Callback.")
   }
}


Now one more important point to give support for Android 10 and Android R. So Let’s talk about it…

Support for Android 10

Step 1: Make these changes in build.gradle file.

  1. Set compileSdkVersion to 29.
  2. Set buildToolsVersion to “29.0.3”.
  3. Set targetSdkVersion to 29.

Your code should look something like this:

android {

  compileSdkVersion 29

  buildToolsVersion “29.0.3”

  defaultConfig {

      applicationId “com.example.android.location”

      minSdkVersion 26

      targetSdkVersion 29

      versionCode 1

      versionName “1.0”

  }

}

Step 2: If you have a foreground service, declare a foregroundServiceType of location in the manifest.

android:foregroundServiceType=”location”

Your code should look something like this:

<application>

   …

   <!– Foreground services in Android 10+ require type. –>

   <service

android:name=”com.example.android.location.ForegroundOnlyLocationService”

       android:enabled=”true”

       android:exported=”false”

       android:foregroundServiceType=”location” />

</application>

Support for Android 11 or Android R

Great news, you don’t need to make changes to any files except for the build.gradle file! Make these changes:

  1. compileSdkVersion to “android-R”
  2. targetSdkVersion to “R”

Your code should look something like this:

android {

  compileSdkVersion “android-R”

  buildToolsVersion “29.0.2”

  defaultConfig {

      applicationId “com.example.android.location”

      minSdkVersion 26

      targetSdkVersion “R”

      versionCode 1

      versionName “1.0”

  }

}



Last Updated : 19 Sep, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads