How to Get Current Location in Android? - GeeksforGeeks

19 Sep, 2021
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:
Android’s Location Manager APIFused Location Provider: Google Play Services Location APIs
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 methods we will have to take 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.
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? = nulllateinit var locationManager: LocationManagerlocationManager = 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).
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 Locationprivate lateinit var locationCallback: LocationCallback  // This will store current location infoprivate 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...
Step 1: Make these changes in build.gradle file.
Set compileSdkVersion to 29.Set buildToolsVersion to “29.0.3”.Set targetSdkVersion to 29.
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>
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”
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”
  }
...
}
Blogathon-2021
Android
Blogathon
How To
Kotlin
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Resource Raw Folder in Android Studio
Flutter - Custom Bottom Navigation Bar
How to Read Data from SQLite Database in Android?
How to Post Data to API using Retrofit in Android?
Retrofit with Kotlin Coroutine in Android
How to Call or Consume External API in Spring Boot?
How to Create a Table With Multiple Foreign Keys in SQL?
Re-rendering Components in ReactJS
Python NOT EQUAL operator
SQL Query to Insert Multiple Rows