Skip to content

Instantly share code, notes, and snippets.

@lmgarret
Last active October 18, 2024 13:36
Show Gist options
  • Save lmgarret/10201a1448ce244c43a1ed846bfc722c to your computer and use it in GitHub Desktop.
Save lmgarret/10201a1448ce244c43a1ed846bfc722c to your computer and use it in GitHub Desktop.
This script takes an ADB backup `backup.ab` of PhoneTrack, and outputs a GPX file with timestamps and other metadata. Run with `uv run --script phonetrack_ab_to_gpx.py`
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "gpxpy",
# "android_backup",
# ]
# ///
import sqlite3
import subprocess
import tarfile
import os
from datetime import datetime
from android_backup.android_backup import AndroidBackup
import gpxpy
import gpxpy.gpx
# Path to your .ab file
backup_ab = "backup.ab"
# Output .tar file
backup_unpacked = "backup.ab.unpacked"
with AndroidBackup(backup_ab) as ab:
ab.unpack(backup_unpacked)
# Verify the file extraction
db_path = os.path.join(backup_unpacked, "apps", "net.eneiluj.nextcloud.phonetrack", "db", "NEXTCLOUD_PHONETRACK")
print(f"DB extracted at: {db_path}")
print(f"Reading PhoneTrack db file...")
# Connect to the SQLite database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Query to retrieve data from the LOCATIONS table
cursor.execute("SELECT LAT, LON, TIME, BEARING, ALTITUDE, SPEED, ACCURACY FROM LOCATIONS")
rows = cursor.fetchall()
print(f"Found {len(rows)} locations")
# Create a GPX object
gpx = gpxpy.gpx.GPX()
# Create a GPX track
gpx_track = gpxpy.gpx.GPXTrack()
gpx.tracks.append(gpx_track)
# Create a GPX track segment
gpx_segment = gpxpy.gpx.GPXTrackSegment()
gpx_track.segments.append(gpx_segment)
# Add points to the GPX segment
for row in rows:
lat, lon, time, bearing, altitude, speed, accuracy = row
gpx_point = gpxpy.gpx.GPXTrackPoint(
latitude=lat,
longitude=lon,
time=datetime.utcfromtimestamp(time),
elevation=altitude
)
gpx_point.bearing = bearing
gpx_point.speed = speed
gpx_point.hdop = accuracy
gpx_segment.points.append(gpx_point)
print("Writing locations to 'output.gpx'...")
# Write the GPX file
with open("output.gpx", "w") as f:
f.write(gpx.to_xml())
print("Done!")
# Close the database connection
conn.close()
@lmgarret
Copy link
Author

lmgarret commented Oct 18, 2024

My previous phone's screen had died and my Nextcloud instance had only records up until 01.2024 even though I was sure to have started the log job in 2022 on the broken phone.

I spent quite some time trying to enable USB debugging to get access to the phone using scrcpy. Once in, I manually exported the logjob to a GPX only to have the same findings as you did: the timestamps are not included. I even saw that a recent commit temporarily disabled the feature so I looked into other means of getting this location data back. Here's how I managed to extract the location data from my phone:

  1. On your computer, go to a dedicated directory for what we will be doing, then open a terminal in there
  2. Start a backup of the application using adb, with:
adb backup -noapk net.eneiluj.nextcloud.phonetrack

this will require accepting the backup on the phone

  1. Once the backup is done, you should have a backup.ab file. It contains the app's database! We will extract it using a small python script I wrote.

  2. Ideally, you should install uv to run the script with its dependencies. You can also manually pip install the script's dependencies and run it.
    The script is here phonetrack_ab_to_gpx.py. It does not take inputs, just run it with uv run --script phonetrack_ab_to_gpx.py

    • First, it will unpack the .ab file into a local dir
    • Then it will open the sqlite db file located at apps/net.eneiluj.nextcloud.phonetrack/db/NEXTCLOUD_PHONETRACK
    • It will go through the points in the LOCATIONS table
    • And write all of them to a output.gpx file
  3. You should now have an output.gpx file with all locations, complete with timestamp, altitude, speed etc...!

Hopefully this very niche script will help somebody :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment