Kotlin Android App Development Course, Getting User Location

In this course, we will explore in detail how to obtain user location in Android apps using Kotlin. Location tracking using GPS and technology is a very important feature in modern mobile apps. By utilizing user location information, we can provide more personalized services.

1. Overview of Android Location Services

In Android, the FusedLocationProviderClient from Google Play services is used to collect location data. This API handles location requests more efficiently and quickly determines the user’s location by utilizing GPS, Wi-Fi, and cellular networks.

2. Project Setup

Before writing direct code, you need to add the required libraries to your project. Please follow the steps below.

2.1. Add Gradle Dependencies

Check the project’s build.gradle file. First, you need to add the following dependency:

implementation 'com.google.android.gms:play-services-location:21.0.1'

2.2. Permissions Setup

To obtain location data, the app needs to request location permissions. Add the following permissions to the AndroidManifest.xml file:


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

3. Obtaining User Location

Now we will write the code to request the location. To do this, we will create an instance of FusedLocationProviderClient and set up the location request.

3.1. Setting Up FusedLocationProviderClient

The following code shows the process of requesting the user’s location in the MainActivity.kt file:


import android.Manifest
import android.content.pm.PackageManager
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.tasks.OnSuccessListener

class MainActivity : AppCompatActivity() {
    private lateinit var fusedLocationClient: FusedLocationProviderClient

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        getLastLocation()
    }

    private fun getLastLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1000)
            return
        }

        fusedLocationClient.lastLocation.addOnSuccessListener(this, OnSuccessListener { location ->
            if (location != null) {
                Toast.makeText(this, "Latitude: ${location.latitude}, Longitude: ${location.longitude}", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(this, "Unable to get location.", Toast.LENGTH_LONG).show()
            }
        })
    }
}
    

3.2. Handling Permission Requests

To handle the location permission request, add the onRequestPermissionsResult method:


override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 1000) {
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            getLastLocation()
        } else {
            Toast.makeText(this, "Location permission denied.", Toast.LENGTH_LONG).show()
        }
    }
}    
    

4. Real-time Location Updates

Now let’s look at how to update the user’s location in real-time. To do this, we will use the LocationRequest object to set up the location request.

4.1. Setting Up LocationRequest

You can request real-time location updates with the code below:


import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest

private lateinit var locationRequest: LocationRequest
private lateinit var locationCallback: LocationCallback

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    createLocationRequest()
    createLocationCallback()
}

private fun createLocationRequest() {
    locationRequest = LocationRequest.create().apply {
        interval = 10000 // Location update interval (10 seconds)
        fastestInterval = 5000 // Fastest update interval (5 seconds)
        priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    }
}

private fun createLocationCallback() {
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: com.google.android.gms.location.LocationResult?) {
            locationResult ?: return
            for (location in locationResult.locations) {
                Toast.makeText(this@MainActivity, "Current location: ${location.latitude}, ${location.longitude}", Toast.LENGTH_LONG).show()
            }
        }
    }
}
    

4.2. Requesting Location Updates

Location requests can be started using the following method:


private fun startLocationUpdates() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED 
        && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
            arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1000)
        return
    }
    fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
}
    

4.3. Stopping Location Updates

If location updates are no longer needed, you can stop them with the method below:


private fun stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback)
}    
    

5. Integrated Code

We will now provide the final code example by integrating the code we have written so far:


import android.Manifest
import android.content.pm.PackageManager
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.google.android.gms.location.*

class MainActivity : AppCompatActivity() {
    private lateinit var fusedLocationClient: FusedLocationProviderClient
    private lateinit var locationRequest: LocationRequest
    private lateinit var locationCallback: LocationCallback

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        createLocationRequest()
        createLocationCallback()
        getLastLocation()
    }

    private fun createLocationRequest() {
        locationRequest = LocationRequest.create().apply {
            interval = 10000 // 10 seconds
            fastestInterval = 5000 // 5 seconds
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
    }

    private fun createLocationCallback() {
        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                locationResult ?: return
                for (location in locationResult.locations) {
                    Toast.makeText(this@MainActivity, "Current location: ${location.latitude}, ${location.longitude}", Toast.LENGTH_LONG).show()
                }
            }
        }
    }

    private fun getLastLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1000)
            return
        }

        fusedLocationClient.lastLocation.addOnSuccessListener(this) { location ->
            if (location != null) {
                Toast.makeText(this, "Latitude: ${location.latitude}, Longitude: ${location.longitude}", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(this, "Unable to get location.", Toast.LENGTH_LONG).show()
            }
        }
    }

    private fun startLocationUpdates() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1000)
            return
        }
        fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
    }

    private fun stopLocationUpdates() {
        fusedLocationClient.removeLocationUpdates(locationCallback)
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 1000) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getLastLocation()
            } else {
                Toast.makeText(this, "Location permission denied.", Toast.LENGTH_LONG).show()
            }
        }
    }
}
    

6. Conclusion

In this course, we learned how to obtain user location in Android using Kotlin. We explored how to utilize GPS and location service APIs to provide personalized services. With this foundation, you can move on to more complex location-based services.

7. Next Steps

Next steps could include displaying the location on a map or implementing radius searching for specific locations. This will provide a richer user experience.

© 2023, Kotlin Android App Development Course. All rights reserved.