Build your own tracking app
Snap and Track

Build a simple and handy solution for recording and tracking locations; in the process, learn how to automate Android and build a simple Python-based app.
A dedicated GPS tracker or a GPS tracking app can come in handy in many situations. Recording and saving your movements can help you geocorrelate photos, keep track of places you've visited, maintain a simple travelogue, and more. Although several excellent apps can be used to transform an Android device into a capable GPS tracker, most of them are one-trick ponies designed to record your location continuously and save the geographical data in the GPX format.
What if you need a tool that does more than that? For example, suppose you want to use your Android device to snap a photo and then save the relevant data – such as date and time, latitude and longitude – in a database or a text file. Wouldn't it be great to have a web-based app that runs on a Linux server and lets you view your snapshots and data using a regular browser? If you have a working knowledge of Python scripting, you can build a tool like this yourself, and this article shows you how to do that.
General Notes and Preparatory Work
The solution you are about to build (I'll call it Geofix) consists of two parts: (1) a simple Python script running on the Android device that automates the process of taking snapshots, collecting the relevant data, and saving it in an SQLite database and (2) a Python-based web app that acts as a front end for viewing the snapshots and the data in the database.
Android doesn't natively support Python scripting, so to run Python scripts on your Android device, you need to install the Scripting Layer for Android (SL4A) and Python for Android packages on it. To do this, grab the latest APK packages of SL4A [1] and Python for Android [2] for the appropriate architecture and install them on the Android device.
Most mainstream Linux distributions come with Python installed by default. That means any machine running a popular Linux distribution like Debian or Ubuntu can be used to run the Geofix web app. Instead of writing a web app from the ground up, you can save a lot of time and effort by using a dedicated web framework. You can choose from several excellent Python web frameworks, and Bottle [3] is probably the simplest and most lightweight of these – which makes it a perfect tool for building the Geofix web app. To install Bottle on a Debian or Ubuntu-powered machine that will serve the web app, run the following commands as root:
apt-get install python-pip pip install bottle
Although Geofix is a relatively simple solution, listing all of its code here is not very practical, so before you proceed, grab the latest version of Geofix [4] from the GitHub repository or clone it using:
git clone https://github.com/dmpop/geofix.git
The Android Python Script
With all the pieces in place, you are ready to dissect and study the geofix.py
Python script that runs on the Android device. This relatively short and simple script performs several actions. To keep things tidy and organized, the script uses dedicated directories for storing the database and snapshots.
The script starts by checking whether the directory specified as a value of the geofix_dir
variable exists. If the directory doesn't exist, the script creates it, along with the snapshots
sub-directory for storing photos:
if not os.path.exists(geofix_dir): os.makedirs(geofix_dir) os.makedirs(geofix_dir + 'snapshots/')
Thanks to so-called facades (friendly wrappers for Android APIs), the SL4A and Python for Android can access and make use of various Android functions. The script uses three facades to toggle location features and obtain geographical data:
droid = android.Android() droid.startLocating() droid.eventWaitFor('location', int(wait)) location = droid.readLocation().result droid.stopLocating()
The startLocating()
facade enables the locating functionality, the eventWaitFor()
facade pauses the script for the period of time specified in the wait
variable to obtain geographical data, and the stopLocating()
facade disables locating. The period of time required to obtain geographical data depends on several factors, and you might need to adjust the default wait
value to give the script enough time to receive the data.
Instead of modifying the wait value in the script, you can add a dialog that lets you specify the wait time on the fly. To do this, replace the wait = 9000
line with the following code:
droid = android.Android() droid.dialogCreateAlert("Wait time") wait = droid.dialogGetInput("Specify wait time in milliseconds:").result
The locating functionality in Android uses two sources to obtain geographical data: the built-in GPS module and mobile network. This ensures that the device is able to obtain the data even if one of the sources is not available. The code block shown in Listing 1 takes care of extracting latitude and longitude values from the received geographical data.
Listing 1
Obtaining Latitude and Longitude Values
The script first attempts to obtain latitude and longitude values from the network source (lines 1-5). If this fails, the script tries to extract coordinates from the GPS source (lines 7-11). Next, the script constructs a string containing the coordinates in the digiKam-compatible format (see the "Geotagging Photos in digiKam" box) and a URL that shows the exact location on the OpenStreetMap map:
Geotagging Photos in digiKam
If you happen to use digiKam as your preferred photo management application, you can use it together with Geofix to geotag photos. Both geofix.py
and geofix.sh
scripts save the geographical coordinates in the digiKam-compatible format. So, to geotag one or several photos in digiKam, just copy the desired coordinates in the digiKam format (e.g., *geo:56.1831455,10.1182492*) from Geofix. Then, switch to digiKam, select the photos you want to geotag, and choose Image | Geo-location. Select the photos, right-click on the selection, and choose Paste coordinates.
digikam = 'geo:' + lat + ',' + lon osm = 'http://www.openstreetmap.org/ index.html?mlat=' + lat + '&mlon=' + lon + '&zoom=18'
The current date and time, latitude, longitude, generated digiKam string, and OpenStreetMap URL are then saved in the geofix.csv
comma-separated file (Listing 2).
Listing 2
Saving Coordinates
In addition to the comma-separated file, the script also writes the data into the geofix.sqlite
SQLite database, which the web app uses as its back end (Listing 3). If the database doesn't exist, the script creates it before writing the data into it (Listing 4).
Listing 3
Writing Data to geofix.sqlite
Listing 4
Creating the Database
Finally, the script takes a photo using the cameraInteractiveCapturePicture
facade. The photo is saved in the dedicated snapshots
directory using the date and time stamp as the photo's file name:
droid.cameraInteractiveCapturePicture(geofix_dir + 'snapshots/' + dt + '.jpg')
To install geofix.py
on your Android device, put it in the sl4a/scripts
directory. Although you can launch the script through the SL4A app, you can also create a shortcut to the script on the home screen. This way, you can run the script with a single tap.
Scripting with Termux
The SL4A and Python for Android combination is not your only option for automating Android. The Termux project [5] equips Android with a terminal emulator and Linux environment. Among other things, this means you can automate Android using Bash shell scripts that make use of popular Linux tools. Better still, the Termux:API add-on enables access to Android's APIs, so you can integrate Android functionality into shell scripts.
Both Termux and Termux:API are available on Google Play Store and F-Droid, so you can install the apps from your preferred source. To replicate the functionality of the geofix.py
Python script, you need to install a couple of Linux tools, including termux-api
, which enables Termux:API functionality, jq
for manipulating data in the JSON format, and sqlite
for working with SQLite databases. To do this, launch Termux and run the following commands:
#apt update #apt upgrade #apt install termux-api jq sqlite
The geofix.sh
script that automates the required tasks is not particularly complicated, but a couple of commands need some explanation. The termux-location
command outputs location data in the JSON format, and to extract latitude and longitude, the script needs to pipe the output to the jq
tool:
lat=$(termux-location | jq '.latitude') lon=$(termux-location | jq '.longitude')
The termux-toast
command can only display text from stdin (the standard input connection), so to show a pop-up message, you need to pipe it to termux-toast
using the echo
command:
echo "Coordinates: $lat, $lon" | termux-toast
The termux-camera-photo
command requires a camera ID value assigned to the -c
or --camera
parameter. Usually, the back camera has ID 0, and the front camera has ID 1. To check the IDs of the cameras on your Android device, run the termux-camera-info
command.
Termux lets you automate tasks on Android using the environment and tools familiar to most Linux users, but it does have a couple of drawbacks compared with SL4A and Python for Android. To run the script (or any Bash shell script for that matter), you need to start the Termux app first and then execute the appropriate command. This can quickly become a serious nuisance if you use the script often. Also, the termux-camera-photo
command doesn't provide any visual feedback, and you have no control of shooting settings.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Direct Download
Read full article as PDF:
Price $2.95
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.
News
-
Armbian 23.05 is Now Available
Based on Debian 12, the latest version of the ARM/RISC-V distribution is now available to download and install.
-
Linux Mint Finally Receiving Support for Gestures
If you use the Linux Mint Cinnamon desktop, you'll be thrilled to know that 21.2 is getting support for gestures on touchscreen devices and touchpads.
-
An All-Snap Version of Ubuntu is In The Works
Along with the standard deb version of the open-source operating system, Canonical will release an-all snap version.
-
Mageia 9 Beta 2 Ready for Testing
The latest beta of the popular Mageia distribution now includes the latest kernel and plenty of updated applications.
-
KDE Plasma 6 Looks to Bring Basic HDR Support
The KWin piece of KDE Plasma now has HDR support and color management geared for the 6.0 release.
-
Bodhi Linux 7.0 Beta Ready for Testing
The latest iteration of the Bohdi Linux distribution is now available for those who want to experience what's in store and for testing purposes.
-
Changes Coming to Ubuntu PPA Usage
The way you manage Personal Package Archives will be changing with the release of Ubuntu 23.10.
-
AlmaLinux 9.2 Now Available for Download
AlmaLinux has been released and provides a free alternative to upstream Red Hat Enterprise Linux.
-
An Immutable Version of Fedora Is Under Consideration
For anyone who's a fan of using immutable versions of Linux, the Fedora team is currently considering adding a new spin called Fedora Onyx.
-
New Release of Br OS Includes ChatGPT Integration
Br OS 23.04 is now available and is geared specifically toward web content creation.