Build an Exercise Tracking App: Persistence & Graphing


Get a free year on Tuts+ this month when you purchase a Siteground hosting plan from $3.95/mo

Welcome to the second and final part in this series of tutorials on developing an Exercise Tracker application with PhoneGap. In this tutorial, we will finish the Track Workout page and complete the app by creating the History and Track Info pages.

Saving the GPS Data

When the user clicks the Stop Tracking button, we need to stop following their GPS location and save all of the GPS points that were recorded (tracking_data) into the database. We'll also reset the text input box (in case they want to record another workout straight away) and we'll display a message that we have stopped location tracking.

PhoneGap provides both browser-based Local Storage and a SQLite database as methods of storing data on the phone. The SQL database is a lot more powerful (due to the fact you can specify table schemas), but comes at the cost of code complexity. Local Storage is a simple key/value store that is easy to setup and use. Data is stored using the setItem(key, value) method, and retrieved using the getItem(key) method.

In the ExerciseTracker app, we need to store tracking_data (the array of Position objects). We set the key to be track_id (the text/ID the user entered for their exercise) and the value to be a string representation of a JSON object of tracking_data. We are forced to convert this array to JSON because Local Storage can only store strings.

Your application can now track the user's workouts and store where they went on the phone!

Useful Development Shortcuts

Now we will add a couple of features to the app which help to reduce development time. On the Home page of ExerciseTracker, you will remember the "Clear Local Storage" and "Load Seed GPS Data" buttons. In the first tutorial, we only declared the markup for them. Now we will code the functionality.

Home page

"Clear Local Storage" and "Load Seed GPS Data" buttons on the Home page.

Like all of our event handling in ExerciseTracker, we use the jQuery live() function to listen for the click event. If the "Clear Local Storage" button is fired, then we call the window.localStorage.clear() method which deletes all entries in the local storage. If the "Load Seed GPS Data" button is fired, then we insert some dummy GPS data into the database.

History Page


Completed History Page

The history page lists all of the workouts the user has recorded. When they click on a workout, we open the Track Info page which contains detailed information (such as distance travelled, time taken, and route plotted on a Google Map). Below is the markup for the history page.

Now we need to code the functionality. When the user loads the page, we need to generate an HTML list containing all of the recorded workouts. Because window.localStorage is just another Javascript object, we can call the length() method on it to find out how many workouts the user has recorded. We can then iterate over our database calling the window.localStorage.key() method (which returns a key for a given index) to find the names of all of the workouts.

Viewing the History page should now show all tracked workouts.

Track Info Page

The Track Info page displays information about an individual workout the user has completed. We will calculate the distance they travelled, the time it took them to complete their workout, and also the route taken on a Google Map.

track info page

Completed Track Info Page

The Track Info page displays dynamic, not static, information. The content of the page depends on what workout the user clicked on from the History page. So, we need some way to communicate what workout was clicked to the Track Info page.

When the user clicks a workout link, we set a track_id attribute to the <div id="track_info"></div> element. Then, when the Track Info page is loaded, we retrieve that track_id and display the appropriate workout information.

Calculating Distance of the Workout

Chris Veness has written a great explanation on how to calculate the distance between two GPS coordinates. I used his code as a base for the gps_distance function.

Now that we have a function to calculate the distance between two GPS coordinates, and an array full of GPS coordinates the user recorded, we can sum all of the individual distances between adjacent points to calculate the total distance the user travelled.

Calculating Workout Duration

Each of the GPS Position objects has a timestamp attribute. We simply subtract the timestamp of the first recorded GPS Position from the last recorded GPS Position to give us the total time taken for the workout in milliseconds. We then do some conversions to calculate the total time in both minutes and seconds.

Plotting the Route on the Google Map

Finally, we need to plot the workout route on a Google Map. We start off by setting the intial latitude and longitude that the Google Map will be centered on as the coordinates of the first GPS point. We then declare the options object which contains various settings for the Google Map. We then create the map, specifying that we want the HTML element with the ID map_canvas to hold the map.

If your map isn't loading, be sure to check that you are providing the correct API key in the <script src=""> of the Google Map API in index.html. With our map created, we can then plot the user's route. We create an array and fill it with instances of google.maps.LatLng substituting the values of each of the GPS points. We then create a google.maps.PolyLine based off of those coordinates and apply the line to the map.


This concludes the tutorial on building the PhoneGap app ExerciseTracker. I hope you have learned a lot about the various technologies we used. If you have any questions please post them in the comments below!