From c30e5089d6e0e30dd9b8c3e6164bd065f393dd7e Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Tue, 12 May 2026 13:47:05 -1000 Subject: fix(track): broaden MediaStore query to find saved GPX files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RELATIVE_PATH equality matching was returning 0 rows — MediaStore normalises the path differently across Android versions and devices. DISPLAY_NAME LIKE nav_%.gpx is unique enough on its own. Also log path + IS_PENDING per found file to aid future diagnosis. Co-Authored-By: Claude Sonnet 4.6 --- .../kotlin/org/terst/nav/track/TrackStorage.kt | 24 +++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'android-app/app/src/main') 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 7e9064c..4147128 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 @@ -114,10 +114,16 @@ class TrackStorage(private val context: Context) { private fun loadViaMediaStore(): List> { val tracks = mutableListOf>() val uri = MediaStore.Files.getContentUri("external") - val projection = arrayOf(MediaStore.Files.FileColumns._ID) - val selection = "${MediaStore.Files.FileColumns.RELATIVE_PATH} = ? " + - "AND ${MediaStore.Files.FileColumns.DISPLAY_NAME} LIKE ?" - val args = arrayOf("Documents/Nav/", "nav_%.gpx") + val projection = arrayOf( + MediaStore.Files.FileColumns._ID, + MediaStore.Files.FileColumns.RELATIVE_PATH, + MediaStore.MediaColumns.IS_PENDING + ) + // Do NOT filter by RELATIVE_PATH — equality matching is fragile across + // Android versions and devices (trailing-slash normalisation, volume prefix, + // etc.). The display-name pattern is specific enough on its own. + val selection = "${MediaStore.Files.FileColumns.DISPLAY_NAME} LIKE ?" + val args = arrayOf("nav_%.gpx") val cursor = runCatching { context.contentResolver.query(uri, projection, selection, args, null) @@ -126,11 +132,15 @@ class TrackStorage(private val context: Context) { }.getOrNull() NavLogger.i("track", "loadViaMediaStore: cursor=${cursor?.count ?: "null"} rows") cursor?.use { c -> - val idCol = c.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID) + val idCol = c.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID) + val pathCol = c.getColumnIndex(MediaStore.Files.FileColumns.RELATIVE_PATH) + val pendingCol = c.getColumnIndex(MediaStore.MediaColumns.IS_PENDING) while (c.moveToNext()) { - val id = c.getLong(idCol) + val id = c.getLong(idCol) + val path = if (pathCol >= 0) c.getString(pathCol) else "?" + val pending = if (pendingCol >= 0) c.getInt(pendingCol) else -1 val fileUri = android.net.Uri.withAppendedPath(uri, id.toString()) - NavLogger.i("track", "loadViaMediaStore: parsing id=$id uri=$fileUri") + NavLogger.i("track", "loadViaMediaStore: id=$id path=$path pending=$pending") runCatching { val stream = context.contentResolver.openInputStream(fileUri) if (stream == null) { -- cgit v1.2.3