How To Make an Android Run Tracking App
Learn how to make an Android run tracking app to show a user’s position on a map, along with their path. By Roberto Orgiu.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How To Make an Android Run Tracking App
30 mins
- Getting Started
- Location, Location, Location
- Getting the User’s Location
- Asking Permission to Get Your User’s Location
- Testing for the First Time
- Showing User Movement
- Presenting Location Data
- Recognizing the User’s Activity
- Asking for Another Permission
- Adding More Glue
- Drawing the UI, At Last!
- Where to Go From Here?
In this tutorial, you’ll learn how to make an Android run tracking app that shows the user’s position on a map, together with their path. This approach is practical when you’re trying to build a tracker for sport sessions, like running or biking. Using the Google Maps API, you can create a tracker with this ability.
Oh, wait… that’s what you’re going to do now!
Along the way, you’ll learn how to:
- Use the Google Maps API inside your Android project.
- Get the user’s last recorded position.
- Get updates on the user’s movements.
- Recognize how the user is moving.
- Plot the user’s path on the map.
Before you start, check out this article on how to use maps on Android, or this article about Activity Recognition. It’s always nice to have some prior knowledge of the topic!
Getting Started
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial. Once you load the project into your IDE, head to the Google Cloud Console and log in with your Google account. On the Credentials page, select a project or create a new one.
Beware, it could take a few minutes!
At the top of the page, click Create Credentials and select API Key. Make sure to copy the API Key because you’ll need it soon. If you get lost in the process, check the official documentation here.
Also, make sure to enable the Maps SDK for Android under the API Library.
Now, back in your IDE, select the two google_maps_api files.
The first is for the debug variant and other is for the release. Then paste your API Key where you see this code:
<resources>
<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR_KEY_HERE</string>
</resources>
You’re ready to build your project for the first time! Click the run button and you’ll see this UI:
There are three data fields at the top of the screen: average pace, elapsed time and distance the user moved in the session. These values change when the user starts to move.
Below is your map. If you don’t see it right away, make sure you correctly pasted your API Key in the previous step and enabled the Maps SDK for Android.
Last but not least, there’s the start and stop button that you’ll use to begin and end tracking the user.
Now, you’re ready to rock!
Location, Location, Location
Before you perform any query related to locations, you need to get your dependencies right.
In the app folder, open build.gradle for the app module. Then paste these lines inside the dependencies
lambda:
implementation 'com.google.android.gms:play-services-maps:17.0.1'
implementation 'com.google.android.gms:play-services-location:18.0.0'
implementation 'com.google.maps.android:android-maps-utils:2.2.3'
implementation 'com.google.maps.android:maps-utils-ktx:3.2.0'
Now, click Sync project and you’re ready to rock!
You need to get the user’s location. This step is composed of two actions that display the user’s position on a map.
First, you’ll get the user’s coordinates, and then you’ll build the logic to ask for the location permission. Once the user grants this permission, you’ll display their position on the map.
Getting the User’s Location
In the main package, create a new class called LocationProvider
and paste this code inside its file:
class LocationProvider(private val activity: AppCompatActivity) {
//1
private val client
by lazy { LocationServices.getFusedLocationProviderClient(activity) }
//2
private val locations = mutableListOf<LatLng>()
//3
val liveLocation = MutableLiveData<LatLng>()
//4
fun getUserLocation() {
client.lastLocation.addOnSuccessListener { location ->
val latLng = LatLng(location.latitude, location.longitude)
locations.add(latLng)
liveLocation.value = latLng
}
}
}
Here’s a code breakdown:
- First, you get the object that you need to get the user’s location. You need the Activity to build it, but since you’ll only invoke it after you ensure your app has the permission, keep it
lazy
, so that theLocationProvider
only creates it when needed. - This line is the list of locations that you’ll need later. At the moment, it only contains the user’s initial position, but that’ll change soon.
- Here’s the
LiveData
that contains the device’s location. You’ll listen to this data in a few minutes! - Finally, here’s your request for the user’s position. You take the client you created lazily and add a listener to it. Whenever it receives a new location, it’ll transform it to a
LatLng
, which contains the location’s latitude and longitude, add it to the list of the locations and emit it through theLiveData
.
Now, you’ll see an IDE warning you that your code isn’t asking for the correct permission. It’s right, for the moment.
So, add this annotation to the top of this class:
@SuppressLint("MissingPermission")
Here, you tell the IDE not to warn you anymore for this class. You’re aware that you don’t have the permission, but you’re about to fix it.
Asking Permission to Get Your User’s Location
Create another class, and call it PermissionManager
. Inside it, paste:
class PermissionsManager(
activity: AppCompatActivity,
private val locationProvider: LocationProvider) {
//1
private val locationPermissionProvider = activity.registerForActivityResult(
ActivityResultContracts.RequestPermission()) { granted ->
if (granted) {
locationProvider.getUserLocation()
}
}
//2
fun requestUserLocation() {
locationPermissionProvider.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
}
Here’s a code breakdown:
- First, you register a callback on the
Activity
when the user grants permission. This callback runs and provides a response as soon as the user presses a button in the permission dialog. If the response is positive, you request the device location with the same class you created in the previous step. - Then, you ask for permission. Whenever your app is ready to display the location, you invoke this function, the system will ask for permission and, as soon as the user taps anything, your callback runs.
With that in place, it’s time to test the app!
Testing for the First Time
Now, head back to MapsActivity.kt, and add these lines at the top. Don’t worry about making them too fancy. You’ll remove them soon since you only need them to test the code you just wrote:
private val locationProvider = LocationProvider(this)
private val permissionManager = PermissionsManager(this, locationProvider)
Now, scroll down to the onMapReady
method, delete all of its content and replace with:
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
//1
locationProvider.liveLocation.observe(this) { latLng ->
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14f))
}
//2
permissionManager.requestUserLocation()
map.uiSettings.isZoomControlsEnabled = true
}
Here’s a code breakdown:
- First, you observe the
LiveData
you created. Once theLocationProvider
gets a new location, it emits it, and you move the camera accordingly. - Next, you use the
PermissionManager
to ask for the needed permission.
When the map is ready, you get the user’s location. Build and run the app. You’ll see your position appear on your device!
If you’re on an emulator, move your location around in the options or even import a GPX path file to see the app update the location automatically!
Now that you have the user’s location take it a step further by showing their movement.