diff options
Diffstat (limited to 'android-app/app/src/main')
| -rw-r--r-- | android-app/app/src/main/AndroidManifest.xml | 18 | ||||
| -rw-r--r-- | android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt | 20 |
2 files changed, 26 insertions, 12 deletions
diff --git a/android-app/app/src/main/AndroidManifest.xml b/android-app/app/src/main/AndroidManifest.xml index 35f8dd3..196932d 100644 --- a/android-app/app/src/main/AndroidManifest.xml +++ b/android-app/app/src/main/AndroidManifest.xml @@ -34,26 +34,30 @@ <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> - <!-- application/gpx+xml: standard MIME type, recognised on Android 12+ --> + <!-- GPX as standard MIME type (used by apps that know the type) --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> <data android:mimeType="application/gpx+xml" /> </intent-filter> - <!-- application/gpx: older variant sent by some file managers and email clients --> + <!-- GPX older variant --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> <data android:mimeType="application/gpx" /> </intent-filter> - <!-- file:// URIs from legacy file managers; extension filtered in code --> + <!-- GPX as XML — Android's MimeTypeMap often maps .gpx to text/xml because + application/gpx+xml isn't in the base system database. Code checks the + display name before parsing. --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> - <data android:scheme="file" android:host="*" android:pathSuffix=".gpx" - android:mimeType="*/*" /> + <data android:mimeType="text/xml" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="application/xml" /> </intent-filter> </activity> </application> 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 82c238e..07adb35 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 @@ -3,6 +3,7 @@ package org.terst.nav import android.Manifest import android.content.Intent import android.content.pm.PackageManager +import android.provider.OpenableColumns import android.util.Log import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -141,12 +142,21 @@ class MainActivity : AppCompatActivity(), SafetyFragment.SafetyListener { private fun handleIncomingGpx(intent: Intent?) { if (intent?.action != Intent.ACTION_VIEW) return val uri = intent.data ?: return - // Accept if the MIME type is gpx-related OR if the URI's last path segment - // ends in .gpx — some Android versions / file managers send application/octet-stream - // for file types they don't recognise. val mime = intent.type ?: contentResolver.getType(uri) ?: "" - val byExtension = uri.lastPathSegment?.lowercase()?.endsWith(".gpx") == true - if (!mime.contains("gpx", ignoreCase = true) && !byExtension) return + when { + // Known GPX MIME types — proceed immediately. + mime.contains("gpx", ignoreCase = true) -> Unit + // Generic XML MIME (text/xml, application/xml): the Android system MimeTypeMap + // often lacks application/gpx+xml for .gpx, so file managers fall back to an + // XML type. Verify the display name before parsing to avoid opening random XML. + mime.contains("xml", ignoreCase = true) -> { + val displayName = contentResolver.query( + uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null + )?.use { c -> if (c.moveToFirst()) c.getString(0) else null } + if (displayName?.lowercase()?.endsWith(".gpx") != true) return + } + else -> return + } lifecycleScope.launch { runCatching { val points = withContext(Dispatchers.IO) { |
