1

I'm trying to delete song file from memory phone memory by this code:

private void deleteSongs(){
    String path = song.getPath();
    File songFile = new File(path);

    Log.d(TAG, "Song exists: " + songFile.exists());
    Log.d(TAG, "Song is directory: " + songFile.isDirectory());
    Log.d(TAG, "Song path: " + songFile.getPath());
    Log.d(TAG, "Song name: " + songFile.getName());

    if(songFile.delete())
        Log.d(TAG, "Song deleted successfully by File.delete()");
    else{
        Log.d(TAG, "Can't delete file by File.delete()");
        if(getActivity().deleteFile(songFile.getName()))
            Log.d(TAG, "Song deleted successfully by Activity.deleteFile()");
        else
            Log.d(TAG, "Can't delete file by Activity.deleteFile()");
    }
}

but it doesn't work. Logcat says:

D/DeleteSongDialog: Song exists: true
D/DeleteSongDialog: Song is directory: false
D/DeleteSongDialog: Song path: /storage/emulated/0/Download/2 sekundowy film-20.m4a
D/DeleteSongDialog: Song name: 2 sekundowy film-20.m4a
D/DeleteSongDialog: Can't delete file by File.delete()
D/DeleteSongDialog: Can't delete file by Activity.deleteFile()

The solution with FileProvider doesn't work for Android >= 8.0 but works on Android 7.0 for example. Maybe somebody has an idea what should I change in my or @CodeToLife code?

Thanks in advance.

Oktawian
  • 334
  • 1
  • 2
  • 16

2 Answers2

2

Replace getActivity().deleteFile(songFile.getName()) with songFile.delete(). Also, make certain that you have the WRITE_EXTERNAL_STORAGE permission, including requesting that permission at runtime on Android 6.0+.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I'm trying to delete this song by `getActivity().deleteFile(songFile.getName())` and `songFile.delete()` - it doesn't work. And yes, I have permission. – Oktawian Dec 28 '18 at 13:53
  • @Oktawian: `deleteFile()` will not work for files in arbitrary locations. `delete()` should work, and I am uncertain why it is not for your situation. – CommonsWare Dec 28 '18 at 14:04
  • On Android 7.0 all works fine. My Android 8.1 makes problems - it need another solution. – Oktawian Dec 28 '18 at 14:20
  • @Oktawian this is because `song.getPath();` does not give you any real filesystem path – pskink Dec 28 '18 at 14:25
  • So what should I do in this situation? – Oktawian Dec 28 '18 at 14:28
  • @Oktawian: You are starting with a variable named `song`. What is this, and where did it come from? If `song` is a `Uri` from somewhere -- as pskink thinks -- then it is very likely that this code will not work in places beyond Android 8.1+. A `Uri` is not a file and should not be treated as such. You can try to delete the content identified by the `Uri` using `ContentResolver`, as pskink suggests, though you may not have rights to do that. Usually, the user will delete content from the app that owns that content, not from arbitrary other apps such as yours. – CommonsWare Dec 28 '18 at 14:36
  • That song came from [this](https://stackoverflow.com/a/13580655/9495357) method (similiar). – Oktawian Dec 28 '18 at 14:41
  • `int column_index = musicCursor.getColumnIndex(MediaStore.Audio.Media.DATA); String path = musicCursor.getString(column_index);` – Oktawian Dec 28 '18 at 14:43
  • @Oktawian: That code was obsolete when it was posted (e.g., `managedQuery()` has been deprecated since 2011). The `DATA` column does not have to point to a filesystem path, let alone one that you are capable of deleting. – CommonsWare Dec 28 '18 at 14:44
  • No, it's model class – Oktawian Dec 28 '18 at 15:03
  • So why I can delete it on Android 7.0? – Oktawian Dec 28 '18 at 15:38
  • @Oktawian: Whatever `song` is, you happen in your limited testing to get a filesystem path to a file that you can delete. In other scenarios, you might get `null`, or a filesystem path to a file that you cannot delete (e.g., on removable storage), or possibly other sorts of values. Rather than assume what `PATH` has, create a `Uri` pointing the song, using the `_ID` value [and `ContentUris.withAppendedId()`](https://developer.android.com/reference/android/content/ContentUris.html#withAppendedId(android.net.Uri,%20long)). Then, try `ContentResolver` and `delete()` with that `Uri`. – CommonsWare Dec 28 '18 at 15:43
  • @Oktawian: Even with the `withAppendedId()` approach that I describe above, you may not have rights to delete the content identified by the `Uri`. – CommonsWare Dec 28 '18 at 15:43
  • What should I use as parameter 'Uri contentUri'? `Uri.fromFile(songFile)`? – Oktawian Dec 28 '18 at 15:54
  • @Oktawian: You use the `Uri` that you get from the `_ID` value and `ContentUris.withAppendedId()`. If you are referring to the `Uri` parameter to `withAppendedId()`, use whatever `Uri` from `MediaStore` that you are querying against. The sample that you linked to used `MediaStore.Audio.Media.EXTERNAL_CONTENT_URI`. – CommonsWare Dec 28 '18 at 15:55
  • @Oktawian: [Here is a sample app](https://github.com/commonsguy/cw-omnibus/tree/v8.13/Java8/VideoLambda) that queries `MediaStore`, lists all of the videos, and plays them. I use `_ID` and `withAppendedId()` to create a `Uri` to use with `ACTION_VIEW` to play the video. – CommonsWare Dec 28 '18 at 15:59
  • @Oktawian: As I have noted repeatedly, you may or may not have the rights to delete the content identified by the `Uri`. That will be the case for all Android versions. – CommonsWare Dec 28 '18 at 16:15
  • Hi again @CommonsWare. I noticed that these methods don't work perfectly. When I delete song - it disappears from device memory but after some time it come back to device memory again. What's the problem? – Oktawian Jan 04 '19 at 10:48
  • @Oktawian: At this point, I recommend that you stop trying to delete a song based solely on its entry in the `MediaStore`. – CommonsWare Jan 04 '19 at 12:10
  • Which way do you recommend? – Oktawian Jan 04 '19 at 12:25
  • @Oktawian: I recommend that you only delete songs that you put on the device in the first place, tracking where you saved them yourself and deleting them from the filesystem (eventually, the `MediaStore` index will catch up). If you want to allow the user to delete arbitrary content, use the Storage Access Framework (e.g., `ACTION_OPEN_DOCUMENT`) to get a `Uri` that has more guarantees that you will be able to delete its content, or add a file picker library to your project and get a `File` that way. – CommonsWare Jan 04 '19 at 12:47
0

@CommonsWare helped me find a solution. I had to change this code on:

Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.getId());
getActivity().getContentResolver().delete(uri, null, null);

Hope it will help you too

Oktawian
  • 334
  • 1
  • 2
  • 16