diff options
3 files changed, 47 insertions, 3 deletions
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt b/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt index bfa285d..8609456 100644 --- a/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt +++ b/android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt @@ -223,7 +223,7 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { hudDepth.text = "—" applyUnitLabels() - NavLogger.i("app", "started") + NavLogger.i("app", "started v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})") setupBottomSheet() setupBottomNavigation() setupHandlers() diff --git a/android-app/app/src/main/kotlin/org/terst/nav/track/TrackRepository.kt b/android-app/app/src/main/kotlin/org/terst/nav/track/TrackRepository.kt index 3c5c9d5..bd79985 100644 --- a/android-app/app/src/main/kotlin/org/terst/nav/track/TrackRepository.kt +++ b/android-app/app/src/main/kotlin/org/terst/nav/track/TrackRepository.kt @@ -107,10 +107,21 @@ class TrackRepository(context: Context) { if (!pastTracksLoaded) { pastTracksLoaded = true NavLogger.i("track", "getPastTracks: loading from storage (first call)") - val stored = storage.loadAllTracks() + var stored = storage.loadAllTracks() NavLogger.i("track", "getPastTracks: storage returned ${stored.size} tracks " + "(points: ${stored.map { it.size }})") - // Merge: put stored tracks behind any in-memory tracks from this session + + if (stored.isEmpty()) { + // Android clears OWNER_PACKAGE_NAME on uninstall; the files survive on + // disk but the MediaStore query finds nothing. Triggering a rescan via + // our app re-registers the files under our package name, restoring ownership. + NavLogger.i("track", "getPastTracks: 0 tracks — triggering MediaScanner rescan") + storage.triggerNavDirRescan() + stored = storage.loadAllTracks() + NavLogger.i("track", "getPastTracks: after rescan: ${stored.size} tracks " + + "(points: ${stored.map { it.size }})") + } + _pastTracks.addAll(stored) NavLogger.i("track", "getPastTracks: total in memory=${_pastTracks.size}") } diff --git a/android-app/app/src/main/kotlin/org/terst/nav/track/TrackStorage.kt b/android-app/app/src/main/kotlin/org/terst/nav/track/TrackStorage.kt index 0951a38..59d7e53 100644 --- a/android-app/app/src/main/kotlin/org/terst/nav/track/TrackStorage.kt +++ b/android-app/app/src/main/kotlin/org/terst/nav/track/TrackStorage.kt @@ -2,11 +2,14 @@ package org.terst.nav.track import android.content.ContentValues import android.content.Context +import android.media.MediaScannerConnection import android.net.Uri import android.os.Build import android.os.Environment import android.provider.MediaStore import android.util.Log +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withTimeoutOrNull import org.terst.nav.ui.NavLogger import java.io.File import java.time.Instant @@ -255,4 +258,34 @@ class TrackStorage(private val context: Context) { ?.takeIf { it.isNotEmpty() } } ?: emptyList() } + + // ── Post-reinstall recovery ─────────────────────────────────────────────── + + /** + * Asks the MediaScanner to re-index Documents/Nav/. When triggered by our + * app, the scanner re-registers each file with OWNER_PACKAGE_NAME set to + * our package, restoring ownership that Android clears on uninstall. + * After this returns, the MediaStore query in [loadAllTracks] will find + * the files again. + */ + suspend fun triggerNavDirRescan() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return + val navDir = File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), + "Nav" + ) + NavLogger.i("track", "triggerNavDirRescan: scanning ${navDir.absolutePath}") + withTimeoutOrNull(10_000L) { + suspendCancellableCoroutine<Unit> { cont -> + MediaScannerConnection.scanFile( + context, + arrayOf(navDir.absolutePath), + null + ) { path, uri -> + NavLogger.i("track", "triggerNavDirRescan: done path=$path uri=$uri") + if (cont.isActive) cont.resume(Unit) + } + } + } ?: NavLogger.e("track", "triggerNavDirRescan: timed out") + } } |
