Bird
Raised Fist0
Android Kotlinmobile~20 mins

Location services in Android Kotlin - Mini App: Build & Ship

Choose your learning style10 modes available
Build: LocationTrackerScreen
This screen shows the user's current latitude and longitude using Android location services.
Target UI
-------------------------
| Location Tracker      |
|-----------------------|
| Latitude:             |
| Longitude:            |
|                       |
| [Get Current Location]|
-------------------------
Display two TextViews for latitude and longitude.
Add a button labeled 'Get Current Location'.
When the button is tapped, request location permission if not granted.
If permission granted, get the last known location and update the TextViews.
Handle permission denial gracefully with a Toast message.
Starter Code
Android Kotlin
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
        }
    }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
Android Kotlin
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.

Final Result
Completed Screen
-------------------------
| Location Tracker      |
|-----------------------|
| Latitude: 37.4219983  |
| Longitude: -122.084  |
|                       |
| [Get Current Location]|
-------------------------
User taps 'Get Current Location' button.
If permission not granted, app asks for location permission.
If user grants permission, latitude and longitude appear in the TextViews.
If permission denied, a Toast message 'Location permission denied' appears.
If location is unavailable, a Toast message 'Location not available' appears.
Stretch Goal
Add a loading indicator while fetching the location.
💡 Hint
Use a ProgressBar and show it when starting to get location, hide it after location is received or on failure.

Practice

(1/5)
1.

What is the main purpose of FusedLocationProviderClient in Android Kotlin?

easy
A. To get the user's current location easily
B. To display a map on the screen
C. To send SMS messages
D. To manage app permissions

Solution

  1. Step 1: Understand the role of FusedLocationProviderClient

    This client combines different location sources to provide the best location data efficiently.
  2. Step 2: Identify its main use

    It is used to get the user's current location easily without managing multiple providers manually.
  3. Final Answer:

    To get the user's current location easily -> Option A
  4. Quick Check:

    Location client = A [OK]
Hint: FusedLocationProviderClient is for getting location, not maps or SMS [OK]
Common Mistakes:
  • Confusing location client with map display
  • Thinking it manages permissions directly
  • Assuming it sends messages
2.

Which of the following is the correct way to request location updates using FusedLocationProviderClient?

val fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient._____
easy
A. requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
B. getLastKnownLocation()
C. startLocationService()
D. requestPermissions()

Solution

  1. Step 1: Identify method to request continuous updates

    The method requestLocationUpdates is used to get ongoing location updates with a request and callback.
  2. Step 2: Check other options

    getLastKnownLocation() gets a single last location, startLocationService() is not a valid method, and requestPermissions() is unrelated to location updates.
  3. Final Answer:

    requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) -> Option A
  4. Quick Check:

    Request updates = D [OK]
Hint: Request updates use requestLocationUpdates with callback [OK]
Common Mistakes:
  • Using getLastKnownLocation for continuous updates
  • Calling non-existent startLocationService method
  • Confusing permission requests with location updates
3.

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")
    }
}
medium
A. NullPointerException
B. Location not found
C. Syntax error
D. Lat: [latitude], Lon: [longitude]

Solution

  1. Step 1: Understand addOnSuccessListener behavior

    This listener runs when location retrieval succeeds, passing a Location object or null.
  2. Step 2: Check the null condition

    If location is not null, it prints latitude and longitude; otherwise, it prints "Location not found".
  3. Final Answer:

    Lat: [latitude], Lon: [longitude] -> Option D
  4. Quick Check:

    Non-null location prints coordinates = C [OK]
Hint: Non-null location prints coordinates, else prints not found [OK]
Common Mistakes:
  • Assuming location is always null
  • Expecting exceptions without null checks
  • Confusing syntax errors with runtime behavior
4.

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()
}
medium
A. Using wrong permission constant
B. Calling startLocationUpdates() before permission check
C. Missing override for onRequestPermissionsResult to handle response
D. No error, code is correct

Solution

  1. Step 1: Check permission request flow

    The code requests permission if not granted, which is correct.
  2. Step 2: Verify handling of permission result

    Missing override of onRequestPermissionsResult means app won't know if permission was granted or denied.
  3. Final Answer:

    Missing override for onRequestPermissionsResult to handle response -> Option C
  4. Quick Check:

    Permission result handler needed = B [OK]
Hint: Always override onRequestPermissionsResult after requesting permissions [OK]
Common Mistakes:
  • Forgetting to handle permission result
  • Using wrong permission string
  • Calling location updates before permission granted
5.

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 ->
    _____
}
hard
A. useLocation(location!!) // force unwrap without null check
B. if (location != null) { useLocation(location) } else { showError("No location") }
C. showError("No location") // ignore non-null case
D. startLocationUpdates() // request continuous updates instead

Solution

  1. Step 1: Check for null safety

    Using if (location != null) ensures safe use of location without crashing.
  2. Step 2: Handle null case properly

    Showing an error message if location is null informs the user gracefully.
  3. Final Answer:

    if (location != null) { useLocation(location) } else { showError("No location") } -> Option B
  4. Quick Check:

    Null check with fallback = A [OK]
Hint: Always check for null before using location to avoid crashes [OK]
Common Mistakes:
  • Forcing unwrap without null check causing crash
  • Ignoring null case leading to no feedback
  • Requesting continuous updates when only one location needed
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard