Skip to content

About

Record and manage rides, runs and hikes on an offline map, with no internet permission at all.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Offline GPX

Get it on F-Droid

Record and manage rides, runs and hikes on an offline map, with no internet permission at all. Tracks are standard GPX files, and maps are optional Mapsforge files you import yourself. Runs on Android 12 or later.

Tracks on an offline map Recording a track A track's stats with speed and elevation charts The track library grouped by category

Features

  • Record tracks in the background with pausing, waypoints and live charts
  • Recordings survive most crashes
  • Speed and elevation charts by distance or time, with zoom
  • Import and export .gpx tracks compatible with other apps
  • Trim, search, sort and categorize tracks
  • Show, hide, export or delete many tracks at once
  • Maps are optional; without one, tracks draw on a blank background
  • All maps share one canvas and don't need to be adjacent

Non-features

  • Anything requiring internet access
  • External device integration
  • Map routing or searching

FAQ

Is internet-based data collection possible? Not through the app itself, which lacks the INTERNET permission and fails to build with it. Android's cloud backup is disabled and only device-to-device transfers are allowed, though some backup apps, such as Seedvault, can use the device-to-device path and store your data wherever they're set to. However, recording needs system location on, so there is no guarantee that Android itself or other apps don't collect that data.
Was AI used? Yes, a large portion of this codebase was written by Claude. However, a significant amount of time and human effort was put into polishing the user interface and ensuring the app stays lightweight with as few permissions as possible.

Building

Needs the Android SDK (sdk.dir in local.properties, or ANDROID_HOME) and any JDK 17+ to start Gradle, which then builds with an installed JDK 21 or fetches one.

./gradlew :app:assembleDebug     # app/build/outputs/apk/debug/app-debug.apk
./gradlew :app:assembleRelease   # app/build/outputs/apk/release/app-release-unsigned.apk

The release build is minified but unsigned; sign it with your own key.

The build fails if any dependency adds a network permission to the merged manifest (CheckNoNetworkPermissions in app/build.gradle.kts).

Testing

./gradlew test                  # JVM unit tests for :core and :app, no device needed
./gradlew coverageVerification  # coverage report in app/build/reports/coverage, with per-file minimums
./gradlew ktlintCheck           # style per .editorconfig; ktlintFormat fixes most of it
./gradlew check                 # all of the above, plus Android lint

Instrumented tests in app/src/androidTest need a connected device or emulator:

./gradlew :app:connectedDebugAndroidTest

Dependencies are checked against gradle/verification-metadata.xml. After changing one, refresh it with a device or emulator connected:

./gradlew --write-verification-metadata sha256 check :app:assembleRelease :app:connectedDebugAndroidTest

Releasing

  1. Bump versionCode and versionName in app/build.gradle.kts, write the notes to fastlane/metadata/android/en-US/changelogs/<versionCode>.txt, and run check and the instrumented tests.

  2. Commit, tag it v<versionName>, and check out the tag. The build embeds the commit hash, so build only from the tagged commit.

  3. Build clean and sign. F-Droid rebuilds each release with Debian's OpenJDK 21 and ships it only if it matches the signed APK on GitHub, which a stale baseline profile from an incremental build would break.

    ./gradlew clean :app:assembleRelease --no-build-cache
    apksigner sign --ks release.jks --alignment-preserved --v1-signing-enabled false --out offline-gpx-<version>.apk app/build/outputs/apk/release/app-release-unsigned.apk
  4. Push the commit and tag, and attach the signed APK to the tag's GitHub release.

Source layout

Path Contents
core/ JVM-only Gradle module, so no Android. model: Track, TrackPoints columns, TrackPoint for single points, GeoBounds. analysis: FixFilter, SpeedWindow, TrackAnalyzer → TrackProfile.
app/…/data/ gpx: streaming parser, writer and relabeller. db: Room. map: MapStore, TileIndex, and the VTM tile source and theme in MapTiles. record: LocationSource, RecordingWal, RecordingService/Controller/Recovery. settings. track: TrackRepository, TrackCache.
app/…/ui/ map: MapScreen, VTM canvas, layers, generated render theme. track: the sheet. chart: hand-rolled Canvas charts. library, record, settings, format, theme, nav.
app/…/di/ AppContainer: manual wiring, no Hilt.
app/src/main/java/org/oscim/ MapFileHeaders, in VTM's package to reach its package-private header reader.
app/schemas/ Room's exported schemas, used by MigrationTest.
fastlane/ F-Droid listing and screenshots. images/icon.png is a 512 px render of the launcher icon's drawables.

app/… is app/src/main/java/dev/samuelq/gpx, which also holds MainActivity and GpxApplication.

License

Offline GPX is licensed under the GPLv3 or any later version. See LICENSE for details.

Bundled libraries are credited within the app at Settings > Libraries.

The test fixture app/src/test/resources/andorra-fragment.map, which is not part of the app, contains map data © OpenStreetMap contributors, available under the Open Database License. It is cut from a mapsforge extract.

About

Record and manage rides, runs and hikes on an offline map, with no internet permission at all.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages