I use MediaStore to get all Images from Android device. Then after I delete some of the Images from File Manager. Followed I use MediaStore again to get Images, and I get all deleted files which is problem.
Why MediaStore returns files that are no longer are on the device(Deleted from device) ?
Code which I am using to retrieve image from MediaStore.
Uri uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
Cursor cursor = activity.getContentResolver().query(uri, projection, null, null, MediaStore.MediaColumns.DATE_ADDED + " DESC");
String ImagePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));
Help to resolve this issue.
Why MediaStore returns files that are no longer are on the device(Deleted from device) ?
Because whatever file manager you used did not do anything to inform the MediaStore about the deletion of the files. MediaStore will find out eventually, but it may be several hours.
You can rescan Media using below code
MediaScannerConnection.scanFile(context, new String[]{imagePath}, null, new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
//something that you want to do
}
});
Related
I use MediaStore to get all video files from Android device. Then I delete some of these videos. Followed I use MediaStore again, and I get all deleted files.
Why MediaStore returns files that are no longer are on the device?
Delete File:
File file = new File(filePath);
file.delete();
Get all video files from device:
public static List<String> getVideoFiles(Context context) {
String[] projection = { MediaStore.Video.Media.DATA };
Cursor cursor = context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null,
null, null);
List<String> videoList = new ArrayList<String>();
while (cursor.moveToNext()) {
videoList.add(cursor.getString(0));
}
Log.i(Constants.LOG_TAG, "get video files, load: " + videoList.size() + " "
+ videoList.toString());
return videoList;
}
MediaStore updates the list of media is not in real time. It needed time to test the relevance of its database. Try to make a call MediaStore after some time.
Or report manually about updating content.
I'm using org.apache.commons.io.FileUtils to move files from one directory to another, like so:
File source = new File("/my/image/directory/image.jpg";
File destination = new File("/new/image/directory/image.jpg");
FileUtils.moveFile(source, destination);
Note that the source directory is an external directory and destination is an internal directory.
After above code is executed, I query to get the files of my internal directory like so:
File vaultDir = ctx.getDir("dir_name", Context.MODE_PRIVATE);
String[] fileList = vaultDir.list();
//Iterate and print file names
This is working as intended. But when i query the MediaStore like so:
ArrayList<GridViewObject> objects = new ArrayList<>();
String[] mProjection = {MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATA};
ContentResolver cr = ctx.getContentResolver();
Cursor mCursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
mProjection,
null,
null,
MediaStore.Images.Media.DEFAULT_SORT_ORDER);
mCursor.moveToFirst();
while (!mCursor.isAfterLast()) {
GridViewObject tmpGridViewObject = new GridViewObject();
tmpGridViewObject.setTitle(mCursor.getString(0));
tmpGridViewObject.setUrl(mCursor.getString(1));
objects.add(tmpGridViewObject);
mCursor.moveToNext();
}
The image is still returned to me by the query. Also, when I open my camera gallery app, the image is still there, as if it was never deleted.
I noticed that if I restart the phone, the image disappears from my device camera gallery app as intended (and above query return correct result). So I think it might be an indexing problem.
What do I need to do to "update" the MediaStore to show the intended result?
I solved this by instead of deleting the file using FileUtils.delete(srcFile, destFile); i copied the the file using FileUtils.copy(srcFile, destFile); and then to refresh MediaStore i used the following code to delete the source entry:
String selection = MediaStore.Images.Media.DATA + "='" + source.getAbsolutePath() + "'";
ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection, null);
Credit goes to Pascal's answer to this question.
I'm using Intent.ACTION_GET_CONTENT which opens recent files. Selecting items from the recent files gives a bad URI but selecting the same file from the file manager gives a right URI which can be handled by my code.
public static String getRealPathFromURI(Context context, Uri uri) {
String path;
if ("content".equals(uri.getScheme())) {
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
path = cursor.getString(idx);
cursor.close();
} else {
path = uri.getPath();
}
return path;
}
Note: The uri.getPath() output when I select a PDF from the recent files is /document/... but selecting the same file from the file manager is, .../emulated/....
Note: the error while selecting the file from the recent files is
Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
The problem was my code doesn't handle the new Layout Storage URIs of Android. If you face this problem too, please refer to this link because the writer is wrote a fantastic method to get real path of every URIs.
I am trying to rename an image in Gallery taken from Camera to give a new name. When I renamed the file the original image disappears showing 2 black squares . Can any one help me in sorting this issue by telling me procedure to rename Gallery Image.
Path is as follows : /mnt/sdcard/DCIM/Camera
I tried to update the Image title through content provider as below:
ContentValues val = new ContentValues();
val.put(Images.Media.TITLE, "ImageTitle23");
getContentResolver().update(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, val, null, null);
The image title is changed in Gallery.
But when I try to query the updated image as below I am getting the name same as previous one :
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, MediaStore.Images.Media._ID+"="+id, null, imageOrderBy);
if(imageCursor.moveToFirst()){
int idd = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
String fullPath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
Can anyone help me in sorting out this issue?
The MediaStore looks for changes in your pictures BUT it will not react to all changes in real time. Each time you do such a modification, you should ask the MediaScanner to scan this file:
MediaScannerConnection.scanFile(
getApplicationContext(),
new String[]{file.getAbsolutePath()},
null,
new OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
Log.v("grokkingandroid",
"file " + path + " was scanned seccessfully: " + uri);
}
});
Also, you should check this blog post that gives a lot of useful informations on this usecase.
The Gallery is interacting with the MediaStore content provider. If you change the name of the image file you probably need to update the field in the content provider.
You can read up on it in the MediaStore reference : http://developer.android.com/reference/android/provider/MediaStore.Images.Media.html
Potentially you can just trigger a refresh of the MediaStore. Look at this thread : How can I refresh MediaStore on Android?
In the class MediaStore.Files class, its mentioned that,
Media provider table containing an index of all files in the media storage, including non-media files.
I'm interested in querying for non-media files like PDF.
I'm using CursorLoader to query the database. The second parameter for the constructor requires an Uri argument which is easy to get for the media types Audio, Images and Video as each of them have a EXTERNAL_CONTENT_URI and INTERNAL_CONTENT_URI constant defined for them.
For MediaStore.Files there is no such defined constant. I tried using the getContentUri() method but couldn't figure out the argument value for volumeName. I tried giving "/mnt/sdcard" and also the volume name that appears when I connect the device to my system but in vain.
I saw a similar question on Google Groups but that is not resolved.
EDIT: I also tried using Uri.fromFile(new File("/mnt/sdcard/")) and Uri.parse(new File("/mnt/sdcard").toString()) but that didn't work out either.
It is "external" or "internal" although internal (system files) is probably not useful here.
ContentResolver cr = context.getContentResolver();
Uri uri = MediaStore.Files.getContentUri("external");
// every column, although that is huge waste, you probably need
// BaseColumns.DATA (the path) only.
String[] projection = null;
// exclude media files, they would be here also.
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE;
String[] selectionArgs = null; // there is no ? in selection so null here
String sortOrder = null; // unordered
Cursor allNonMediaFiles = cr.query(uri, projection, selection, selectionArgs, sortOrder);
If you want .pdf only you could check the mimetype
// only pdf
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
String[] selectionArgsPdf = new String[]{ mimeType };
Cursor allPdfFiles = cr.query(uri, projection, selectionMimeType, selectionArgsPdf, sortOrder);