can't delete file from external storage in android programmatically
Asked Answered
I

4

16

I am trying to delete a file located at the path

/storage/714D-160A/Xender/image/Screenshot_commando.png

What I've done so far:

  try{
        String d_path = "/storage/714D-160A/Xender/image/Screenshot_commando.png";
        File file = new File(d_path);
        file.delete();

     }catch(Exception e){

        e.printStackTrace();
     }

and the file is still at its place(Not deleted :( )

Also I've given permission in Manifest file.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.STORAGE" />
Imponderabilia answered 22/7, 2017 at 10:59 Comment(8)
What error you are gettng? add your logcat details.Formic
If you are testing on a device with Android M or greater, you'll need runtime permission.Wholesome
i testing on a device with android MImponderabilia
not show any error in log-cat, file is still at its placeImponderabilia
did you request permission programmatically?Buseck
yes i give all permission programmatically, but not work for me....Imponderabilia
File.delete() doesn't throw IOEexceptions. It returns a boolean, which you are ignoring.Codex
@EJP thank's for your replay, but boolean return false and the file is still at its place(Not deleted)Imponderabilia
I
15
public static boolean delete(final Context context, final File file) {
    final String where = MediaStore.MediaColumns.DATA + "=?";
    final String[] selectionArgs = new String[] {
            file.getAbsolutePath()
    };
    final ContentResolver contentResolver = context.getContentResolver();
    final Uri filesUri = MediaStore.Files.getContentUri("external");

    contentResolver.delete(filesUri, where, selectionArgs);

    if (file.exists()) {

        contentResolver.delete(filesUri, where, selectionArgs);
    }
    return !file.exists();
}
Imponderabilia answered 24/7, 2017 at 11:43 Comment(4)
Will this method work with Android devices running on Android 5.0 and above?Geomorphic
No, it doesn't work on Android 5.0 and will cause many problems. In fact, editing files on the sd-card is not that easy but it is doable. See my answer.Galang
hii @Imponderabilia one suggestion A good answer will always have an explanation of what was done and why it was done in such a manner, not only for the OP but for future visitors to SO. so if possible please edit and explain in few words :)Lorrinelorry
what is "external" in getContentUri("external") ? - @ImponderabiliaUnzip
G
12

Using ContentResolver to delete media files is wrong and provides many problems for the user.
You can not delete a file on the sd-card simply by deleting its information from the ContentResolver on Android versions greater than Jelly Bean(4.3).
It works only on Android versions prior to KitKat(4.4).
That's why the Android team provided DocumentProvider.

Why contentResolver.delete(...) is wrong?
1. Fills up the sd-card
When you try to delete a media file on the sd-card by the ContentResolver on Android versions greater than 4.3, the actual media file will remain untouched because the contentResolver.delete(...) approach only removes the information (name, date, path ...) of the media and you will end up having unregistered media files on your sd-card which ContentResolver has no idea about their existence anymore and that's why you couldn't see them in your gallery and you think they've been deleted with this approach while they're still there and fill up the sd-card each time the user tries to delete a media file on the sd-card.

2. Media files (Images, videos, gifs ...) will come back to the gallery
There are many apps out there especially gallery and file manager ones that will find these unregistered media files and will add them to the ContentResolver again as of their normal behavior while the user assumes his/her unwanted media files are gone. Sure no user wants his/her assuming deleted images or videos show up in the middle of a demonstration.

So, what's the correct approach to remove media files on the sd-card?
Well, this has already been answered here with the use of DocumentProvider.

Galang answered 31/7, 2017 at 0:54 Comment(2)
The original question never even mentioned ContentResolver. Why does your answer focus on it? OH. I see. the accepted answer uses contentresolver.Saddlecloth
The original question never even mentioned ContentResolver. Why does your answer focus on it? OH. I see. the accepted answer uses contentresolver. @Saddlecloth No. Your assumption is wrong and illogical. I've already answered the question to explain how to use ContentResolver in the correct way, almost one year before the accepted answer appears and talks about ContentResolver which is wrong and irresponsible. Here is the link also provided in my answer >> https://mcmap.net/q/176187/-android-saf-storage-access-framework-get-particular-file-uri-from-treeuriGalang
P
5

From Android 4.4 onwards, you can't write to SD card files (except in the App directory) using the normal way. You'll have to use the Storage Access Framework using DocumentFile for that.

The following code works for me:

private void deletefile(Uri uri, String filename) {
    DocumentFile pickedDir = DocumentFile.fromTreeUri(this, uri);

    DocumentFile file = pickedDir.findFile(filename);
    if(file.delete())
        Log.d("Log ID", "Delete successful");
    else
        Log.d("Log ID", "Delete unsuccessful");
}

where filename is the name of the file to be deleted and uri is the URI returned by ACTION_OPEN_DOCUMENT_TREE:

private static final int LOCATION_REQUEST = 1;

private void choosePath() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    intent.addCategory(Intent.CATEGORY_DEFAULT);
    startActivityForResult(intent, LOCATION_REQUEST);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    if (requestCode == LOCATION_REQUEST && resultCode == Activity.RESULT_OK) {
        if (resultData != null) {
            Uri uri = resultData.getData();
            if (uri != null) {
                /* Got the path uri */
            }
        }
    }
}
Pabulum answered 4/7, 2018 at 11:56 Comment(8)
In this "private void deletefile(Uri uri, String filename)" need file name as well, but how can I get file name from uri got in activityresult...Tumpline
@BhaveshMoradiya Sorry for the late reply, I was a bit busy. I use the following for getting the path from the URI: String path = FileUtil.getFullPathFromTreeUri(uri, this);. The FileUtil class can be found here: https://mcmap.net/q/176188/-android-5-0-documentfile-from-tree-uriPabulum
@BhaveshMoradiya The URI that you get via ACTION_OPEN_DOCUMENT_TREE is not a particular file, but rather, a location. You'll need to use ACTION_OPEN_DOCUMENT if you want the user to pick a particular filePabulum
DocumentFile file = pickedDir.findFile(filename); returns npe for some reason?Paralytic
Found the reason why, i had to select the folder where the files where located; but how can i automatically open that folder so the users doesn't have to browser to that folder?Paralytic
@Vince Try pickedDir = DocumentFile.fromFile(new File(location)); DocumentFile file = pickedDir.findFile(fileName); if(file == null) { /* File not found */ } else { if(file.delete()) { /* Success! */ } else { /* Failed to delete */ } }Pabulum
also, won't this open a dialogue? people would like to obtain the uri from the native app interface, e.g. by taping the song name on a music player, is there a way to get the uri in another way?Vereeniging
@Vereeniging Yes ACTION_OPEN_DOCUMENT_TREE will open a dialog for selecting a path. I'm not sure if there is a way to get a tree URI without using that.Pabulum
B
3

Use Environment.getExternalStorageDirectory().getAbsolutePath() instead of hard coding storage path

String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
File f = new File(baseDir + "/714D-160A/Xender/image/Screenshot_commando.png");
boolean d = f.delete();
Buseck answered 23/7, 2017 at 7:55 Comment(5)
thank's for your answer but i want to delete external storage(Memory Card) file.and boolean return false,the file is still at its place(Not deleted)..Imponderabilia
@Imponderabilia Did you test Environment.getExternalStorageDirectory().getAbsolutePath() instead of /storage ?Buseck
@Imponderabilia I'm pretty sure that the problem is in file address. Test another file which is located in your external storage rootBuseck
@Secret, Hi I'm also looking for method which able to delete file from External Memory Card(Physically Mounted Memory), Do you get solution ? Please Help me..Tumpline
@BhaveshMoradiya you need ExternalStoragePermission and then simply call File.delete() for your fileBuseck

© 2022 - 2024 — McMap. All rights reserved.