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.