How to refresh Android's MediaStore upon photo

2019-04-09 00:48发布

问题:

Question: how to make the media store to refresh its entry of a DELETED file?

After deleting a photo in code from the external storage, I still see a slot for the deleted photo in the gallery - blank photo.

It seems that the gallery reflects the media store and the deleted photo is found in the media store until the phone is restarted or generally - until the media is rescanned.

Trying to scan the deleted file did not help scanning deleted files (works just for new or existing files): MediaScannerConnection.scanFile(Application.get(), new String[]{file.getPath()}, null, null) (I tried scanning the parent folder as well).

Also tried ACTION_MEDIA_SCANNER_SCAN_FILE to no avail. Example: Application.get().sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)))

Sending a broadcast receiver to rescan the entire external storage (thus refreshing the media store)did the trick: Application.get().sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.fromFile(Environment.getExternalStorageDirectory())))

BUT, it seems that Android, as of 4.4, throws a security exception when trying to manually send the ACTION_MEDIA_MOUNTED system broadcast. See @CommonsWare's post: http://commonsware.com/blog/2013/11/06/android-4p4-permission-regressions.html

So, I'm stuck with no solution for refreshing the media store upon file(/photo/video/etc.) deletion.

回答1:

I found the following that works for me in 4.4 on a Nexus 10.

// request scan
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, SELECT_PICTURE);
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(refreshFile));
sendBroadcast(scanIntent);

"refreshFile" is the file I deleted that I get from my String "fPath" and then convert it to a file.

String filePath = fPath;        
File refreshFile = new File(filePath);


回答2:

Try

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

Add this to your manifest:

<intent-filter>
      <action android:name="android.intent.action.MEDIA_MOUNTED" />
      <data android:scheme="file" /> 
</intent-filter>


回答3:

I had the same question as you now that the sendBroadcast approach is disallowed in 4.4 and found a good solution here using the Media Store content provider: https://stackoverflow.com/a/20780472/1060805

I tested it out on Android 4.4 and it works nicely. I think it is a solid approach.



回答4:

I had the same issue. I wrote the following code and it worked on all versions from lollipop to oreo. Adding the code below

    // fileID == MediaStore.Images.Media._ID; for the file when you get the file from the content 
// resolver
public static boolean deleteCREntryForFilePath(Context context, String filePath, long fileID) {
    boolean         fDeleted       = false;
    ContentResolver cr             = context.getContentResolver();
    int             rowsDeleted    = 0;
    Uri             imageURI       = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    String          deleteStr      = MediaStore.Images.Media._ID + "=" + fileID;


    // Remove entry from database
    rowsDeleted = context.getContentResolver().delete(
            imageURI, deleteStr, null);
    if (rowsDeleted > 0)
        fDeleted = true;
    return(fDeleted);
}