------------------------- | Location Tracker | |-----------------------| | Latitude: | | Longitude: | | | | [Get Current Location]| -------------------------
Location services in Android Kotlin - Mini App: Build & Ship
package com.example.locationapp import android.Manifest import android.content.pm.PackageManager import android.location.Location import android.os.Bundle import android.widget.Button import android.widget.TextView import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationServices class LocationTrackerScreen : AppCompatActivity() { private lateinit var fusedLocationClient: FusedLocationProviderClient private lateinit var latitudeTextView: TextView private lateinit var longitudeTextView: TextView private lateinit var getLocationButton: Button override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_location_tracker) latitudeTextView = findViewById(R.id.latitudeTextView) longitudeTextView = findViewById(R.id.longitudeTextView) getLocationButton = findViewById(R.id.getLocationButton) fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) getLocationButton.setOnClickListener { // TODO: Add permission check and get location } } }
package com.example.locationapp import android.Manifest import android.content.pm.PackageManager import android.location.Location import android.os.Bundle import android.widget.Button import android.widget.TextView import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationServices class LocationTrackerScreen : AppCompatActivity() { private lateinit var fusedLocationClient: FusedLocationProviderClient private lateinit var latitudeTextView: TextView private lateinit var longitudeTextView: TextView private lateinit var getLocationButton: Button private val requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted: Boolean -> if (isGranted) { getLastLocation() } else { Toast.makeText(this, "Location permission denied", Toast.LENGTH_SHORT).show() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_location_tracker) latitudeTextView = findViewById(R.id.latitudeTextView) longitudeTextView = findViewById(R.id.longitudeTextView) getLocationButton = findViewById(R.id.getLocationButton) fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) getLocationButton.setOnClickListener { when { ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED -> { getLastLocation() } else -> { requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) } } } } private fun getLastLocation() { fusedLocationClient.lastLocation .addOnSuccessListener { location: Location? -> if (location != null) { latitudeTextView.text = "Latitude: ${location.latitude}" longitudeTextView.text = "Longitude: ${location.longitude}" } else { Toast.makeText(this, "Location not available", Toast.LENGTH_SHORT).show() } } .addOnFailureListener { Toast.makeText(this, "Failed to get location", Toast.LENGTH_SHORT).show() } } }
This solution uses Android's FusedLocationProviderClient to get the last known location.
We check if the app has permission to access fine location. If not, we request it using the Activity Result API, which is the modern way to handle permissions.
When permission is granted, we call getLastLocation() to fetch the location and update the UI TextViews with latitude and longitude.
If permission is denied or location is unavailable, we show a friendly Toast message to inform the user.
------------------------- | Location Tracker | |-----------------------| | Latitude: 37.4219983 | | Longitude: -122.084 | | | | [Get Current Location]| -------------------------
Practice
What is the main purpose of FusedLocationProviderClient in Android Kotlin?
Solution
Step 1: Understand the role of FusedLocationProviderClient
This client combines different location sources to provide the best location data efficiently.Step 2: Identify its main use
It is used to get the user's current location easily without managing multiple providers manually.Final Answer:
To get the user's current location easily -> Option AQuick Check:
Location client = A [OK]
- Confusing location client with map display
- Thinking it manages permissions directly
- Assuming it sends messages
Which of the following is the correct way to request location updates using FusedLocationProviderClient?
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient._____Solution
Step 1: Identify method to request continuous updates
The methodrequestLocationUpdatesis used to get ongoing location updates with a request and callback.Step 2: Check other options
getLastKnownLocation()gets a single last location,startLocationService()is not a valid method, andrequestPermissions()is unrelated to location updates.Final Answer:
requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) -> Option AQuick Check:
Request updates = D [OK]
- Using getLastKnownLocation for continuous updates
- Calling non-existent startLocationService method
- Confusing permission requests with location updates
What will the following Kotlin code print if the location is successfully retrieved?
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
if (location != null) {
println("Lat: ${location.latitude}, Lon: ${location.longitude}")
} else {
println("Location not found")
}
}Solution
Step 1: Understand addOnSuccessListener behavior
This listener runs when location retrieval succeeds, passing a Location object or null.Step 2: Check the null condition
If location is not null, it prints latitude and longitude; otherwise, it prints "Location not found".Final Answer:
Lat: [latitude], Lon: [longitude] -> Option DQuick Check:
Non-null location prints coordinates = C [OK]
- Assuming location is always null
- Expecting exceptions without null checks
- Confusing syntax errors with runtime behavior
Identify the error in this Kotlin snippet for requesting location permission:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1)
} else {
startLocationUpdates()
}Solution
Step 1: Check permission request flow
The code requests permission if not granted, which is correct.Step 2: Verify handling of permission result
Missing override ofonRequestPermissionsResultmeans app won't know if permission was granted or denied.Final Answer:
Missing override for onRequestPermissionsResult to handle response -> Option CQuick Check:
Permission result handler needed = B [OK]
- Forgetting to handle permission result
- Using wrong permission string
- Calling location updates before permission granted
You want to get the user's location only once and handle the case when location is null. Which Kotlin code snippet correctly does this?
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
_____
}Solution
Step 1: Check for null safety
Usingif (location != null)ensures safe use of location without crashing.Step 2: Handle null case properly
Showing an error message if location is null informs the user gracefully.Final Answer:
if (location != null) { useLocation(location) } else { showError("No location") } -> Option BQuick Check:
Null check with fallback = A [OK]
- Forcing unwrap without null check causing crash
- Ignoring null case leading to no feedback
- Requesting continuous updates when only one location needed
Ready to prove it?
Pass the test and this pattern moves unknown
