10

I have a DocumentFile defined in following two ways:

DocumentFile documentFile;
Uri documentFileUri;

I can delete a document file from the sd card via following methods:

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

But non of the above methods will delete the corresponding entry from the MediaStore.

What's the correct way to handle that? If I use the ContentProvider for deleting a local file, it will remove the File AND the row from the database (contentResolver.delete(localFileUri, null, null);). I would expect the same to happen if I use the DocumentsContract but it does not happen...

What I want

I want to instandly update the MediaStore. Normally I would call contentResolver.delete(documentFileUri, null, null); but this will fail with an exception that says, that the uri does not support deletions...

Question

Is there a more efficiant way to do it than my workaround?

Workaround

Currently I use following function to instantly update the media store after I deleted a 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;
}
prom85
  • 16,896
  • 17
  • 122
  • 242
  • Why are you using DocumentFile to work with things in MediaStore? They don't seem to be related concepts. If you want to work with MediaStore, then stick to only the objects and functions defined within its API. Also, polling loop bad. :-( – Doug Stevenson Mar 06 '16 at 21:19
  • Because Android will index the sd card even on android 6 which will result in files from the sd card in the media store... So I have to consider this and I have to mix `MediaStore` and `DocumentFile` and keep both in sync when changing files on the sd card... And the loop is bad of course(that's why I called it workaround), I would like to directly update the media store instead which I can do in many ways for local files, but I could not find on for `DocumentFile` on the sd card... – prom85 Mar 06 '16 at 21:22
  • But what does DocumentFile give you that MediaStore won't? Why wouldn't you just use MediaStore APIs for everything? – Doug Stevenson Mar 06 '16 at 21:24
  • 1
    Because you don't have permissions to write on the sd card. You need to use the `Storage Access Framework` on android 6 to get write access on the sd card, so you need to use `DocumentFile` there... Working with paths and the `File` class will not work because of missing permissions... There is not other way than that on android 6 anymore... – prom85 Mar 06 '16 at 21:26
  • It's not clear to me what exactly are you trying to accomplish. Can you not simply query the MediaStore for the file/document you're looking for? – Doug Stevenson Mar 06 '16 at 21:29
  • I will copy/move/delete/rename files on the internal storage, on the sd card and between them. Without using the `DocumentFile` class and the `Storage Access Framework` I won't be able to make ANY changes on the sd card on android 6. Sadly, using the `DocumentFile` and its partner classes does not update the madia store (although the media store will index the not writeable sd card). More about the restrictions and how it works can be found here: http://stackoverflow.com/questions/26744842/how-to-use-the-new-sd-card-access-api-presented-for-lollipop – prom85 Mar 06 '16 at 21:33
  • What I want concretely is in my main post: I want to delete a file from my sd card AND remove the corresponding entry from the `MediaStore`... deleting is not possible via the `MediaStore` because of missing permissions in there, deleting via the `DocumentFile` is possible but does not respect the `MediaStore`... – prom85 Mar 06 '16 at 21:34
  • OK, so can you query the appropriate MediaStore for the file you're looking for, then delete it also using MediaStore? – Doug Stevenson Mar 06 '16 at 21:45
  • No. Deleting via `MediaStore` does not work... No permissions. Trying to do so will throw an exception with the information, that the corresponding `ContentProvider` does not support deletions (which does make sense, because then you would bypass the `Storage Access Framework` and it's permission system) – prom85 Mar 06 '16 at 21:48
  • But a DocumentFile uri won't be recognized by MediaStore. It uses a different way to represent the underlying resource. I'm suggesting that a MediaStore uri may behave differently. – Doug Stevenson Mar 06 '16 at 21:49
  • That's correct. The uri from the `MediaStore` does not work for editing files but can be used to create `File` objects that are readable only... Querying the `MediaStore`will list all files on internal storage and on the sd card, but creating `File` objects with those uris will create files that are readable for sd card files and readable/writeable for files on the internal storage... So if I delete a image from the sd card and don't delete the corresponding row from the `MediaStore`, a gallery app will show this image as present... of course it can't read nor write this image anymore... – prom85 Mar 06 '16 at 21:53
  • 1. How dow you get `DocumentFile` on your sd card? 2. How do you provide `documentFileUri` for `DocumentsContract.deleteDocument(contentResolver, documentFileUri);` to work? – Eftekhari Aug 08 '16 at 19:34
  • "So if I delete a image from the sd card and don't delete the corresponding row from the MediaStore, a gallery app will show this image as present" if you see your image in gallery app you still have that image on your device. Answer my previous question to check more in details. – Eftekhari Aug 08 '16 at 19:45
  • @prom85 got any solution ?? – fatboy Jul 28 '19 at 15:36
  • @fatboy no, only the solution posted inside my question... But this one is working – prom85 Jul 29 '19 at 07:07
  • Try this [link](https://stackoverflow.com/a/20719235/1679754) for deleteing file from MediaStore – Jignesh Mayani Aug 06 '19 at 05:07
  • 1
    @prom85 https://issuetracker.google.com/issues/138887165 this is what i got from google – fatboy Aug 06 '19 at 15:55
  • thanks for the google issue links - for me this means, that my solution is the way to go if an immediate media store update is desired... – prom85 Aug 12 '19 at 07:40
  • @Eftekhari "if you see your image in gallery app you still have that image on your device" - this is not true. This depends on the gallery app implementation and in 99% those galleries use the media store (a database) to get all media for the sake of speed (search the file system would be a lot slower). – prom85 Aug 12 '19 at 07:45
  • @prom85 That's exactly the point. Even if one percent of galley or file manager apps could find it that means you didn't delete the file from the device but only the signature of those files is deleted and that means the user loses space gradually unless you format the memory or the device from time to time, let alone the fact that the file is reachable with some processes and it is not good for the safety or preference of the user. – Eftekhari Aug 12 '19 at 12:06
  • @prom85 The correct approach to delete a file on the sd-card: https://stackoverflow.com/questions/39054454/android-saf-storage-access-framework-get-particular-file-uri-from-treeuri/39104124?noredirect=1#comment100799307_39104124 – Eftekhari Aug 12 '19 at 12:12
  • You misunderstand this, it's the other way round - the file is deleted but their is still a database entry in the media store - pointing to a file that is not existing anymore. So 99% of gallery apps will show a DELETED file (no file on the file system anymore, but an entry for this file in the database still exists). And if you read my question, I know how to delete a file and I know how to update the media store immediately, I was just looking for a more convenient way... – prom85 Aug 13 '19 at 06:30
  • Our discussion is not productive for the issue (read the "what I want" part of my question), fact is, I know how to delete the file, I know how to update the media store (the database) and in the meantime my question is answered by the google issue - google says what I have discovered is by design and this means, my manual force update of the media store (what I already did when I asked this question) is the way to go to get a consistent state between file system and media store without waiting for the next automatic scan or device reboot (which would result in a rescan as well). – prom85 Aug 13 '19 at 06:33

1 Answers1

1

As fatboy pointed out, the behaviour is by design - documented in this google issue: https://issuetracker.google.com/issues/138887165

Solution:

There probably is no better solution than what I already posted in my question than following:

  • delete the file via DocumentFile object or with it's URI and DocumentsContract.deleteDocument
  • for an instant media store update (that's what I wanted) you must manually update the media store, e.g. by calling MediaScannerConnection.scanFile(...) like I already posted it in my question
prom85
  • 16,896
  • 17
  • 122
  • 242
  • Thanks! I am also trying to achieve a similar thing. BTW, how did you get the local absolute path from the documentFile? – Ankit Batra Sep 13 '20 at 22:19