В моем приложении есть функция удаления файлов (может быть любой файл на устройстве). Я регистрирую свои попытки удаления файлов, а затем выделю проблемы, с которыми столкнулся. Устройство, на котором я тестировал, работало под управлением Android 10 (API 29), но мне нужно удалить файлы SD-карты из API 21 и выше.
Подход 1. Удаление с помощью ContentResolver
Этот подход отлично работает с памятью телефона и памятью SD-карты, за исключением того, что я не могу удалить файлы из папки «Загрузки» SD-карты, в то время как то же самое работает с папкой «Загрузки» памяти телефона.
applicationContext.contentResolver.delete(file.uri, null, null)
Я провел некоторое исследование и наткнулся на сообщение SO, где рекомендуемый подход к удалению файлов на SD-карте — через DocumentsProvider
или с помощью DocumentFile
.
Подход 2: удаление с помощью DocumentFile
Я последовал этому ответу и прошел uri дерева документов, получил файл и вызвал delete()
. К моему замешательству, delete()
возвращает true
, но не удаляет файл. Этот подход даже не удалял файлы из других папок на SD-карте, в то время как подход 1 мог это сделать.
Разрешение, которое у меня есть для дерева документов SD-карты, было принято следующим образом.
fun openSafTreePicker(){
val intent = Intent(ACTION_OPEN_DOCUMENT_TREE).apply {
flags = FLAG_GRANT_PERSISTABLE_URI_PERMISSION
or FLAG_GRANT_READ_URI_PERMISSION
or FLAG_GRANT_WRITE_URI_PERMISSION
}
startActivityForResult(intent, requestCode)
}
// On activity result taking the persistable permission
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
val uri = data.data!!
val flags = (data.flags) and (FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION)
applicationContext.contentResolver.takePersistableUriPermission(uri, flags)
AppPrefs.sdCardUri = uri
Log.d(TAG, AppPrefs.sdCardUri)
// AppPrefs.sdCardUri = content://com.android.externalstorage.documents/tree/EAB3-F2BF%3A
// Delete the selected files
val selection = SelectionManager.getEntireSelection()
selection.forEach {
when {
it.isSdFile -> deleteSdCardFile(it.path)
it.isPhoneFile -> applicationContext.contentResolver.delete(it.uri, null, null)
}
}
}
Я попытался удалить файл, используя статические методы, доступные в DocumentsContract
. Мне не удалось удалить файлы с SD-карты, а deleteDocument()
вернул true
.
private fun deleteSdCardFile(filePath: String) {
val segments = filePath.split("/")
// Skip first 3 segments /storage/ABC-1234/0/ corresponding to storage volume and user.
val docPath = StringBuilder()
for (index in 3 until segments.size) {
if(index < segments.size-1) docPath.append(segments[index]).append("/")
else docPath.append(segments[index])
}
val treeUri = Uri.parse(AppPrefs.sdCardUri)
val docUri = DocumentsContract.buildDocumentUriUsingTree(treeUri, docPath.toString())
DocumentsContract.deleteDocument(applicationContext.contentResolver, docUri)
}
Вопросы:
- Как правильно удалить файлы с SD-карты? MediaStore работает нормально, за исключением папки SD-карты
Downloads
. - В чем загадка файлов, которые не удаляются из папки «Загрузки» SD-карты.
- Почему
delete()
иdeleteDocument()
изDocumentFile
иDocumentsContract
возвращают true, даже если они не удалили файл?
flags = FLAG_GRANT_PERSISTABLE_URI_PERMISSION or FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION
Удалите эти флаги. Они бесполезны. ВЫ ничего не можете предоставить. Вы должны быть рады, что вам предоставлен доступ. Вы можете проверить эти флаги в onActivityResult, чтобы узнать, разрешено ли вам чтение или запись. - person blackapps   schedule 09.01.2021val treeUri = Uri.parse(AppPrefs.sdCardUri)
Пожалуйста, покажите более полный код. Для начала мы хотим точно увидеть значение sdCardUri. Адаптируйте свой пост, пожалуйста. - person blackapps   schedule 09.01.2021// docPath is the relative file...
Пожалуйста, опубликуйте полный код. - person blackapps   schedule 09.01.2021DocumentFile.fromTreeUri()
, а затем перешел к нужному файлу, рекурсивно используяdocument.findFile()
. Благодарю вас! - person Siddharth Kamaria   schedule 09.01.2021