diff --git a/app/src/main/java/com/topjohnwu/magisk/core/utils/MediaStoreUtils.kt b/app/src/main/java/com/topjohnwu/magisk/core/utils/MediaStoreUtils.kt index f50da38cd..f9a17bc85 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/utils/MediaStoreUtils.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/utils/MediaStoreUtils.kt @@ -1,6 +1,5 @@ package com.topjohnwu.magisk.core.utils -import android.annotation.SuppressLint import android.content.ContentResolver import android.content.ContentUris import android.content.ContentValues @@ -40,15 +39,17 @@ object MediaStoreUtils { private val relativePath get() = relativePath(Config.downloadDir) - @RequiresApi(api = 29) + @RequiresApi(api = 30) @Throws(IOException::class) private fun insertFile(displayName: String): MediaStoreFile { val values = ContentValues() values.put(MediaStore.MediaColumns.RELATIVE_PATH, relativePath) values.put(MediaStore.MediaColumns.DISPLAY_NAME, displayName) - // before Android 11, MediaStore can not rename new file when file exists, - // insert will return null. use newFile() instead. + // When a file with the same name exists and was not created by us: + // - Before Android 11, insert will return null + // - On Android 11+, the system will automatically create a new name + // Thus the reason to restrict this method call to API 30+ val fileUri = cr.insert(tableUri, values) ?: throw IOException("Can't insert $displayName.") val projection = arrayOf(MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DATA) @@ -65,14 +66,8 @@ object MediaStoreUtils { throw IOException("Can't insert $displayName.") } + @RequiresApi(api = 29) private fun queryFile(displayName: String): UriFile? { - if (Build.VERSION.SDK_INT < 30) { - // Fallback to file based I/O pre Android 11 - val parent = File(Environment.getExternalStorageDirectory(), relativePath) - parent.mkdirs() - return LegacyUriFile(File(parent, displayName)) - } - val projection = arrayOf(MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DATA) // Before Android 10, we wrote the DISPLAY_NAME field when insert, so it can be used. val selection = "${MediaStore.MediaColumns.DISPLAY_NAME} == ?" @@ -92,11 +87,17 @@ object MediaStoreUtils { return null } - @SuppressLint("NewApi") @Throws(IOException::class) - fun getFile(displayName: String): UriFile { - return queryFile(displayName) ?: - /* this code path will never happen pre 29 */ insertFile(displayName) + fun getFile(displayName: String, skipQuery: Boolean = false): UriFile { + if (Build.VERSION.SDK_INT < 30) { + // Fallback to file based I/O pre Android 11 + val parent = File(Environment.getExternalStorageDirectory(), relativePath) + parent.mkdirs() + return LegacyUriFile(File(parent, displayName)) + } + + return if (skipQuery) insertFile(displayName) + else queryFile(displayName) ?: insertFile(displayName) } fun Uri.inputStream() = cr.openInputStream(this) ?: throw FileNotFoundException()