VeloSpot v1.0.27
Added
- Pause & resume a ride β for commuters who hop on a train or ferry mid-way β ride recording can now be paused and later resumed, so a daily bike-to-work commute that includes, say, a 30 km train leg (or a ferry crossing) is captured as one ride without the in-between counting. While paused, incoming GPS fixes are discarded so the pause adds no distance and no time, and the elapsed timer freezes and continues exactly where it left off; the first fix after resuming opens a new track segment, so the skipped stretch is stored as a real gap rather than a straight line drawn across it. The gap survives everywhere the track does: it is persisted (and crash-recovered) via a new
TrackPoint.segmentStartflag, exported as a separate<trkseg>in the GPX file (the portable, Strava/Garmin-friendly way to store an interruption), and drawn as multiple polyline segments on the map (live and for saved rides) via a pure, JVM-testableList<TrackPoint>.splitIntoSegments(). Pause/resume is reachable from every recording surface: the live map overlay, the ongoing notification, the home-screen widget, the quick-settings tile, and the navigation screen (the recording pauses while the route guidance keeps running). Covered byRideTrackerTest,GpxWriterTestandTrackSegmentsTest. Localised across all eight supported languages.
Changed
- Drop the F-Droid product flavor β VeloSpot is now a single Google Play build β the
distributionflavor dimension (fdroid/googlePlay) is removed. The app builds one unbundled variant that uses Google Play Services'FusedLocationProviderClientfor location (the previousLocationManager-based F-DroidLocationRepositoryImpl/LocationModuleare gone). The flavor-specificsrc/googlePlay/β¦sources moved intosrc/main/β¦,play-services-locationis now a plainimplementationdependency, and all tooling that was pinned to a flavor was retargeted to the plain variant: Kover (koverXmlReportDebug), the CycloneDX SBOM (releaseRuntimeClasspath), and the CI/lint workflows (assembleDebug,testDebugUnitTest,lintDebug). The F-Droid-only reproducibilityvcsInfo { include = false }block was dropped (the AGP dependency-metadata block is still kept out of the APK). Docs (README,CONTRIBUTING,RELEASING,ATTRIBUTIONS,SCREENSHOTS) updated accordingly. - Automated Google Play release β signed AAB + fastlane upload from CI β
release.ymlnow builds a signed App Bundle (bundleRelease) alongside the sideload APK and, on avX.Y.Ztag, uploads the AAB plus the store listing and per-version "What's New" changelogs (fastlane/metadata/android) to Google Play via fastlanesupply(newGemfile,fastlane/Appfile,fastlane/Fastfile). The upload runs only when thePLAY_SERVICE_ACCOUNT_JSONsecret is set and defaults to theproductiontrack withdraftstatus (the release is staged in the Play Console for a final manual "Publish"); a manual Run workflow lets you pick the track (internal/alpha/beta/production) and status. The GitHub Release now attaches the AAB and the universal APK (VeloSpot-vX.Y.Z.apk) instead of two flavor APKs. - Bike paths are now preferred over gravel tracks (
trekking.brf,shortest.brf,PROFILES_VERSION11 β 12) β a rider reported that the trekking profile (the default for ordinary riders on a normal bike) picked a gravel track (Schotterweg) even though a dedicated cycleway (Fahrradweg) ran only a few metres away. Both profiles now detect gravel / loose unpaved surfaces (surface=gravel|pebblestone|rock|unpaved|ground|dirt|earth|mud|sand) and add a surcharge to such tracks, so a proper bike path β or a paved way β clearly wins, while the gravel track stays usable when there is no reasonable alternative. The shortest profile previously ignored the surface entirely (every way cost the same), so it crossed gravel whenever it was marginally shorter; it now applies the same surcharge. The fastbike profile already priced unpaved tracks well above a cycleway and is left unchanged.PROFILES_VERSIONis bumped so the updated profiles replace the stale copies in internal storage on existing installs. Covered by a newBRouterGravelAvoidanceTest(which evaluates the real BRouter cost factor and asserts trekking, shortest and fastbike all price a gravel track well above a cycleway), plus the existingBRouterProfileIntegrityTestandBRouterProfileRoutabilityTest.
Fixed
- Crash when the address search returned duplicate hits β searching for a place could crash the app with
IllegalArgumentException: Key "β¦" was already usedfrom the resultsLazyColumn. The list key wasdisplayName + latitude, which is not unique: Nominatim can return several hits that share the same display name and latitude (e.g. a place plus its administrative boundary), so two rows collided. The results list is ephemeral and never reordered, soAddressSearchBarnow keys theLazyColumnby the item index (viaitemsIndexed), which is guaranteed unique, and draws the row divider usingindex < results.lastIndex.
π₯ Artifacts
| File | Description |
|---|---|
VeloSpot-v1.0.27.apk |
Universal APK, ready to sideload |
app-release.aab |
Android App Bundle (uploaded to Google Play) |
VeloSpot-v1.0.27-sbom.cdx.json / .xml |
CycloneDX SBOM β full dependency + license inventory |
π Supply-chain verification
All release artifacts ship with signed build provenance attestations.
Verify any downloaded file with the GitHub CLI:
gh attestation verify VeloSpot-v1.0.27.apk --repo drzeeb/VeloSpotInstallation (sideload)
- Download the APK below.
- On your Android device: Settings β Apps β Install unknown apps β allow your browser or file manager.
- Open the APK and tap Install.