Getting the User Location
Fused location provider basics.
Getting the User Location is a free Android Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Where Is the User?
Most location-aware apps start with one question: where is the device right now? Android answers this through the Fused Location Provider, part of Google Play services.
In this lesson you'll add the dependency, request a single location, listen for continuous updates, and surface the result in Compose.
Why the Fused Provider
Android has several location sources: GPS, Wi-Fi, and cell towers. The Fused Location Provider intelligently blends them to give you the best location with the least battery drain.
You almost never use raw LocationManager directly anymore — the fused client is simpler and smarter.
// build.gradle.kts (module)
dependencies {
implementation("com.google.android.gms:play-services-location:21.3.0")
}Declaring the Permission
Location is a sensitive resource. Declare the permission in your AndroidManifest.xml. Use ACCESS_FINE_LOCATION for precise positioning or ACCESS_COARSE_LOCATION for approximate.
Declaring it is only step one — you must also request it at runtime (covered in a later lesson).
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />Creating the Fused Client
Get a FusedLocationProviderClient from LocationServices. In Compose, grab the context with LocalContext.current and remember the client so it isn't recreated each recomposition.
import com.google.android.gms.location.LocationServices
@Composable
fun rememberFusedClient() = run {
val context = LocalContext.current
remember {
LocationServices.getFusedLocationProviderClient(context)
}
}Getting the Last Known Location
The fastest answer is lastLocation — the most recent fix the system already cached. It returns a Task, so attach a success listener.
It can be null if no app has requested a location recently, so always null-check.
@SuppressLint("MissingPermission")
fun fetchLastLocation(
client: FusedLocationProviderClient,
onResult: (Location?) -> Unit
) {
client.lastLocation
.addOnSuccessListener { location -> onResult(location) }
.addOnFailureListener { onResult(null) }
}Awaiting the Task with Coroutines
Callbacks nest quickly. The kotlinx-coroutines-play-services library adds .await() so you can read a location with clean suspending code.
import kotlinx.coroutines.tasks.await
@SuppressLint("MissingPermission")
suspend fun currentLastLocation(
client: FusedLocationProviderClient
): Location? {
return client.lastLocation.await()
}Requesting a Fresh Location
lastLocation may be stale. For an up-to-date fix, call getCurrentLocation with a priority. PRIORITY_HIGH_ACCURACY uses GPS; PRIORITY_BALANCED_POWER_ACCURACY saves battery.
import com.google.android.gms.location.Priority
import com.google.android.gms.location.CurrentLocationRequest
@SuppressLint("MissingPermission")
suspend fun freshLocation(
client: FusedLocationProviderClient
): Location? {
val request = CurrentLocationRequest.Builder()
.setPriority(Priority.PRIORITY_HIGH_ACCURACY)
.build()
return client.getCurrentLocation(request, null).await()
}Continuous Location Updates
For navigation or tracking you need a stream of updates. Build a LocationRequest with an interval, then register a LocationCallback via requestLocationUpdates.
Always stop updates when you're done to save battery.
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationCallback
val request = LocationRequest.Builder(
Priority.PRIORITY_HIGH_ACCURACY,
5000L // 5 seconds
).build()
val callback = object : LocationCallback() {
override fun onLocationResult(result: LocationResult) {
result.lastLocation?.let { /* use it */ }
}
}Updates as a Flow
A clean pattern wraps updates in a callbackFlow, so consumers collect locations and updates stop automatically when collection ends via awaitClose.
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow
@SuppressLint("MissingPermission")
fun FusedLocationProviderClient.locationFlow(request: LocationRequest) = callbackFlow {
val cb = object : LocationCallback() {
override fun onLocationResult(result: LocationResult) {
result.lastLocation?.let { trySend(it) }
}
}
requestLocationUpdates(request, cb, Looper.getMainLooper())
awaitClose { removeLocationUpdates(cb) }
}Showing Location in Compose
Collect the result in a composable using LaunchedEffect for a one-shot read, or collectAsStateWithLifecycle for a stream. Then display the coordinates.
@Composable
fun LocationLabel(client: FusedLocationProviderClient) {
var location by remember { mutableStateOf<Location?>(null) }
LaunchedEffect(Unit) {
location = freshLocation(client)
}
Text(
location?.let { "Lat ${it.latitude}, Lng ${it.longitude}" }
?: "Locating..."
)
}Battery and Accuracy Trade-offs
Location is one of the biggest battery costs in mobile apps. Choose the lowest accuracy that still meets your needs, use the longest acceptable update interval, and always stop updates when the screen is gone.
High accuracy + frequent updates drains batteries fast — reserve it for active navigation.
Quick Check
You need the single most accurate current position right now, using a suspending function. Which approach fits best?
Recap
You can now read the device location:
- Add
play-services-locationand declareACCESS_FINE/COARSE_LOCATION. - Get a
FusedLocationProviderClientfromLocationServices. - Use
lastLocationfor a cached fix,getCurrentLocationfor a fresh one. - Stream updates via
requestLocationUpdates/ acallbackFlow, and stop them to save battery.
Next: drawing markers and moving the camera to those coordinates.
Frequently asked questions
Is the “Getting the User Location” lesson free?
Yes — the full text of “Getting the User Location” is free to read here on the web, and the Android Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.
What will I learn in “Getting the User Location”?
Fused location provider basics. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Android Academy?
No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Getting the User Location” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Android Academy lesson?
Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Showing a Map
- Getting the User Location
- Markers and Camera
- Location Permissions Done Right