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.
This commit is contained in:
MohitMaliFtechiz 2024-02-07 19:12:07 +05:30
parent 1f078634ae
commit 05dbd4b38b

View File

@ -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>
): 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
}
}