From 05dbd4b38be29f227b8bf2be67bcccca7c572763 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Wed, 7 Feb 2024 19:12:07 +0530 Subject: [PATCH] Fixed: Kiwix 3.9.1 and Wikivoyage 2023-12 apps were crashing when attempting to open ZIM files on Fire OS 7.3.2.9. * Enhanced the `queryForActualPath()` method to retrieve the actual path for a URI. Users faced a `java.lang.UnsupportedOperationException: Unknown URI` exception when querying the contentResolver with an invalid URI. A check has been added to prevent such errors. * On older devices, the download URI contains the full file path, causing the `documentProviderContentQuery` to fail in retrieving the path, leading to unexpected behavior (failure to open the ZIM file). The code has been improved to handle this scenario. * In certain devices, the content URI prefix may differ, and using only `public_downloads` to obtain the actual path from the URI might not work if the device has a different URI prefix. The code has been enhanced to consider every possible content prefix when retrieving the actual path. --- .../kiwixmobile/core/utils/files/FileUtils.kt | 65 +++++++++++++++---- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt index b5222394b..5e02319e0 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt @@ -49,6 +49,7 @@ import java.io.BufferedReader import java.io.File import java.io.FileNotFoundException import java.io.IOException +import java.lang.NumberFormatException object FileUtils { @@ -156,18 +157,58 @@ object FileUtils { return null } - private fun documentProviderContentQuery(context: Context, uri: Uri) = - contentQuery( - context, - ContentUris.withAppendedId( - Uri.parse("content://downloads/public_downloads"), - try { - DocumentsContract.getDocumentId(uri).toLong() - } catch (ignore: NumberFormatException) { - 0L - } - ) + private fun documentProviderContentQuery(context: Context, uri: Uri): String? { + // Extracting the document ID from the URI. + val documentId = extractDocumentId(uri) + + // Attempt to handle cases where the document ID is a direct path to a ZIM file. + if (isValidZimFile(documentId)) { + return documentId.substringAfter("raw:") + } + + // Try different content URI prefixes in some case download content prefix is different. + val contentUriPrefixes = arrayOf( + "content://downloads/public_downloads", + "content://downloads/my_downloads", + "content://downloads/all_downloads" ) + val actualDocumentId = try { + documentId.toLong() + } catch (ignore: NumberFormatException) { + 0L + } + return queryForActualPath(context, actualDocumentId, contentUriPrefixes) + } + + private fun queryForActualPath( + context: Context, + documentId: Long, + contentUriPrefixes: Array + ): String? { + try { + for (prefix in contentUriPrefixes) { + val contentUri = ContentUris.withAppendedId(Uri.parse(prefix), documentId) + val path = contentQuery(context, contentUri) + + if (path != null) { + return path + } + } + } catch (ignore: Exception) { + // do nothing + } + + return null + } + + private fun extractDocumentId(uri: Uri): String { + try { + return DocumentsContract.getDocumentId(uri) + } catch (ignore: Exception) { + // Log or handle the exception if needed + } + return "" + } private fun contentQuery( context: Context, @@ -185,6 +226,8 @@ object FileUtils { null } catch (ignore: NullPointerException) { null + } catch (ignore: UnsupportedOperationException) { + null } }