Правильно удалите DocumentFile (соблюдая MediaStore)

У меня есть DocumentFile определяется следующими двумя способами:

DocumentFile documentFile;
Uri documentFileUri;

Я могу удалить файл документа с SD-карты следующими способами:

  1. documentFile.delete();
  2. DocumentsContract.deleteDocument(contentResolver, documentFileUri);

Но ни один из вышеперечисленных методов не удалит соответствующую запись из MediaStore,

Какой правильный способ справиться с этим? Если я использую ContentProvider для удаления локального файла, он удалит File И строка из базы данных (contentResolver.delete(localFileUri, null, null);). Я ожидаю, что то же самое произойдет, если я использую DocumentsContract но этого не происходит...

Что я хочу

Я хочу по-настоящему обновить MediaStore, Обычно я бы позвонил contentResolver.delete(documentFileUri, null, null); но это не удастся, за исключением того, что URI не поддерживает удаления...

Вопрос

Есть ли более эффективный способ сделать это, чем мой обходной путь?

Временное решение

В настоящее время я использую следующую функцию для мгновенного обновления хранилища мультимедиа после удаления DocumentFile:

public static boolean updateAfterChangeBlocking(String path, int timeToWaitToRecheckMediaScanner)
{
    final AtomicBoolean changed = new AtomicBoolean(false);
    MediaScannerConnection.scanFile(StorageManager.get().getContext(),
            new String[]{path}, null,
            new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) {
                    changed.set(true);
                }
            });

    while (!changed.get()) {
        try {
            Thread.sleep(timeToWaitToRecheckMediaScanner);
        } catch (InterruptedException e) {
            return false;
        }
    }

    return true;
}

1 ответ

Как отметил Толстяк, поведение является заданным - задокументировано в этой проблеме Google: https://issuetracker.google.com/issues/138887165

Решение:

Вероятно, нет лучшего решения, чем то, что я уже написал в своем вопросе, чем следующее:

  • удалить файл через DocumentFile объект или это URI а также DocumentsContract.deleteDocument
  • для мгновенного обновления медиа-магазина (это то, что я хотел), вы должны вручную обновить медиа-магазин, например, позвонив MediaScannerConnection.scanFile(...) как я уже разместил в своем вопросе

Я немного опоздал, но я надеюсь, что приду с решением проблемы... даже спустя 2 года с момента публикации этого вопроса. Полный пример кода можно найти здесь https://drive.google.com/file/d/1zCdaGwslr5XfWH_t0iZPKDukChOLXMg3/view?usp=sharing. (написано на Kotlin) Этот код работал для меня для версии Android LOLLIPOP и выше.

Код прост и его легко понять.

Этот менеджер файлов с открытым исходным кодом имеет функцию удаления файлов, которая вам нужна

https://github.com/TeamAmaze/AmazeFileManager/blob/master/app/src/main/java/com/amaze/filemanager/filesystem/FileUtil.java

https://github.com/TeamAmaze/AmazeFileManager/blob/master/app/src/main/java/com/amaze/filemanager/filesystem/MediaStoreHack.java

static boolean deleteFile(@NonNull final File file, Context context) {
        // First try the normal deletion.
        if (file == null) return true;
        boolean fileDelete = rmdir(file, context);
        if (file.delete() || fileDelete)
            return true;

        // Try with Storage Access Framework.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && FileUtil.isOnExtSdCard(file, context)) {

            DocumentFile document = getDocumentFile(file, false, context);
            return document.delete();
        }

        // Try the Kitkat workaround.
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
            ContentResolver resolver = context.getContentResolver();

            try {
                Uri uri = MediaStoreHack.getUriFromFile(file.getAbsolutePath(), context);
                resolver.delete(uri, null, null);
                return !file.exists();
            } catch (Exception e) {
                Log.e(LOG, "Error when deleting file " + file.getAbsolutePath(), e);
                return false;
            }
        }

        return !file.exists();
    }
Другие вопросы по тегам