Latest Method: How to get Current Location (Latitude and Longitude) in Android & Give support for all Android Versions including Android 10 and Android R
By: Kapil Sachan
Tags: Kotlin, Android Location, Android App Development

Latest Method: How to get Current Location (Latitude and Longitude) in Android & Give support for all Android Versions including Android 10 and Android R Kapil Sachan Dec 26, 2020·6 min read

Get Current Location (Latitude and Longitude) in Android

This tutorial helps you to learn How to get the current latitude and longitude in the Android.

As a developer when you work on locations, maps, or any new component of Android then you always have some doubts about selecting the best and efficient approach for your requirement. But don’t worry, I will try to clear all your doubts with my articles on all doubtful topics of Android in my coming Articles.

So let’s focus on our today’s topic: How to get the Current Location (Latitude and Longitude) in Android.

There are two ways to get the current location of any Android device:

→ Android’s Location Manager API

→ 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 method we will have to take location permission.

Important: Taking Location Permission

Step 1: Define uses permissions for location access in manifest.

<!-- 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" />

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.

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 learn how can we get location in android.

First Method: By Android’s Location Manager API

Note: We assume that user has granted Location Permission. If not then ask first.

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

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 is available then we use one with greater accuracy.

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

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

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 provider is enabled then we will request a current location update from the LocationManager with LocationListener.

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 more accurate location and then we will use that location as per our requirment.

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

}

}

Finally, I am providing a gist with all steps.

Now after learning how can we get 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

Note: We assume that user has 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 location 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.

/* 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.

fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

Step 3: Initialize locationRequest.

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.

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.

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.

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.")

}

}

Finally I am providing a gist with all steps.

Cheers! You have done this :)

Now one more important point to give support for Android 10 and Android R.

So Let’s talk about it…

Support for Android 10

Your app already subscribes to location changes, so there isn’t a lot of work to do.

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

Set compileSdkVersion to 29 . Set buildToolsVersion to "29.0.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:

compileSdkVersion to "android-R" 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"

}

...

}

Thank you for reading 😊.

Stay safe and Keep Coding ✌.

Now you are able to get the current latitude and longitude on your android device. If you have any issue regarding the same, please put it in the comment section.