I save an image to the sdcard and it doesn't appear in the Gallery application until I pull off the sdcard and return it back.
Do you have any idea why is it so?
Seems like the Gallery application has some cache that isn't updated on file save...
Actually, I also want to open the just-saved image in Gallery application and have no success with that this is my question about this issue.
A simpler solution is to use the static convenience method scanFile():
File imageFile = ...
MediaScannerConnection.scanFile(this, new String[] { imageFile.getPath() }, new String[] { "image/jpeg" }, null);
where this is your activity (or whatever context), the mime-type is only necessary if you are using non-standard file extensions and the null is for the optional callback (which we don't need for such a simple case).
My answer to the original question and to anyone else that may have this problem:
I was having this same problem, images in my app that people saved to the SD card were not showing up in their Gallery immediately. After some searching I found this one line of code inserted after my 'save to sdcard' code that fixed the problem:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
The system scans the SD card when it is mounted to find any new image (and other) files. If you are programmatically adding a file, then you can use this class:
http://developer.android.com/reference/android/media/MediaScannerConnection.html
You can also add an Image to the Media Gallery by intent, have a look at the example code to see how it is done:
ContentValues image = new ContentValues();
image.put(Images.Media.TITLE, imageTitle);
image.put(Images.Media.DISPLAY_NAME, imageDisplayName);
image.put(Images.Media.DESCRIPTION, imageDescription);
image.put(Images.Media.DATE_ADDED, dateTaken);
image.put(Images.Media.DATE_TAKEN, dateTaken);
image.put(Images.Media.DATE_MODIFIED, dateTaken);
image.put(Images.Media.MIME_TYPE, "image/png");
image.put(Images.Media.ORIENTATION, 0);
File parent = imageFile.getParentFile();
String path = parent.toString().toLowerCase();
String name = parent.getName().toLowerCase();
image.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
image.put(Images.Media.SIZE, imageFile.length());
image.put(Images.Media.DATA, imageFile.getAbsolutePath());
Uri result = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
Gallery refresh including Android KITKAT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
else
{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}
Here is the code for the MediaScannerConnection:
MyMediaConnectorClient client = new MyMediaConnectorClient(newfile);
MediaScannerConnection scanner = new MediaScannerConnection(context, client);
client.setScanner(scanner);
scanner.connect();
newfile is the File object of your new/saved file.
there is an app in the emulator that says - ' Dev Tools'
click on that and select ' Media Scanning'.. all the images ll get scanned
Let your activity implement 'MediaScannerConnectionClient'
and add this to your activity:
private void startScan()
{
if(conn!=null) conn.disconnect();
conn = new MediaScannerConnection(YourActivity.this,YourActivity.this);
conn.connect();
}
#Override
public void onMediaScannerConnected() {
try{
conn.scanFile(yourImagePath, "image/*");
} catch (java.lang.IllegalStateException e){
}
}
#Override
public void onScanCompleted(String path, Uri uri) {
conn.disconnect();
}
this work with me
File file = ..... // Save file
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
File folderGIF = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/newgif2"); //path where gif will be stored
success = folderGIF.mkdir(); //make directory
String finalPath = folderGIF + "/test1.gif"; //path of file
.....
/* changes in gallery app if any changes in done*/
MediaScannerConnection.scanFile(this,
new String[]{finalPath}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
Here I am sharing code that can load image in form of bitmap from and save that image on sdcard gallery in app name folder.
You should follow these steps
Download Image Bitmap first
private Bitmap loadBitmap(String url) {
try {
InputStream in = new java.net.URL(url).openStream();
return BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Please also provide following permission in your AndroidManifest.xml file.
uses-permission android:name="android.permission.INTERNET"
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
Here is whole code that is written in Activty in which we want to perform this task.
void saveMyImage(String appName, String imageUrl, String imageName) {
Bitmap bmImg = loadBitmap(imageUrl);
File filename;
try {
String path1 = android.os.Environment.getExternalStorageDirectory()
.toString();
File file = new File(path1 + "/" + appName);
if (!file.exists())
file.mkdirs();
filename = new File(file.getAbsolutePath() + "/" + imageName
+ ".jpg");
FileOutputStream out = new FileOutputStream(filename);
bmImg.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
ContentValues image = new ContentValues();
image.put(Images.Media.TITLE, appName);
image.put(Images.Media.DISPLAY_NAME, imageName);
image.put(Images.Media.DESCRIPTION, "App Image");
image.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
image.put(Images.Media.MIME_TYPE, "image/jpg");
image.put(Images.Media.ORIENTATION, 0);
File parent = filename.getParentFile();
image.put(Images.ImageColumns.BUCKET_ID, parent.toString()
.toLowerCase().hashCode());
image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, parent.getName()
.toLowerCase());
image.put(Images.Media.SIZE, filename.length());
image.put(Images.Media.DATA, filename.getAbsolutePath());
Uri result = getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
Toast.makeText(getApplicationContext(),
"File is Saved in " + filename, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
Hope that it can solve your whole problem.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
Does not seem to work on KITKAT. It throws permission denial exception and crashes the app.
So for this, I have done the following,
String path = mediaStorageDir.getPath() + File.separator
+ "IMG_Some_name.jpg";
CameraActivity.this.sendBroadcast(new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri
.parse("file://" + path)));
Hope it helps.
Use this after saving the image
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
My code for MyMediaConnectorClient:
public class MyMediaConnectorClient implements MediaScannerConnectionClient {
String _fisier;
MediaScannerConnection MEDIA_SCANNER_CONNECTION;
public MyMediaConnectorClient(String nume) {
_fisier = nume;
}
public void setScanner(MediaScannerConnection msc){
MEDIA_SCANNER_CONNECTION = msc;
}
#Override
public void onMediaScannerConnected() {
MEDIA_SCANNER_CONNECTION.scanFile(_fisier, null);
}
#Override
public void onScanCompleted(String path, Uri uri) {
if(path.equals(_fisier))
MEDIA_SCANNER_CONNECTION.disconnect();
}
}
You need to give permissions to the Gallery app.
Just long press the gallery app icon in the home screen and tap on 'APP INFO' that pops up at the top of the screen. Doing it will show the gallery app settings. Now go in Permissions tab and enable the storage, camera permissions by toggling it.
Now go to your native gallery app and you will get the your saved images.
This will aslo solve your problem if your image in gallery are not showing instead they might showing a 404 type bitmap in midle.
please add a the tags that are in my code with your image because there must some meta data in order to show image in gallery.
String resultPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES)+
getString(R.string.directory) + System.currentTimeMillis() + ".jpg";
new File(resultPath).getParentFile().mkdir();
try {
OutputStream fileOutputStream = new FileOutputStream(resultPath);
savedBitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e2) {
e2.printStackTrace();
}
savedBitmap.recycle();
File file = new File(resultPath);
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "Photo");
values.put(MediaStore.Images.Media.DESCRIPTION, "Edited");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis ());
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
values.put(MediaStore.Images.ImageColumns.BUCKET_ID, file.toString().toLowerCase(Locale.US).hashCode());
values.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, file.getName().toLowerCase(Locale.US));
values.put("_data", resultPath);
ContentResolver cr = getContentResolver();
cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
return resultPath;
Try this one, it will broadcast about a new image created, so your image visible. inside a gallery.
photoFile replace with actual file path of the newly created image
private void galleryAddPicBroadCast() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(photoFile);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
Related
i am new to android, i copied files to /storage/sdcard1 from host pc using adb push.
But unable to view the file from gallery application.It is showing through ls command and when i rebooted the device , gallery application showing files properly.But immediately it is not updating in gallery , so can any one help me out for this?
Thanks in advance
You'll have to notify the media scanner to capture metadata of the newly created files. Apps like Gallery work on the metadata database and not directly on the filesystem.
Programmatically you'd use MediaScannerConnection.
Since you're working with adb, you can send a broadcast to invoke media scanner.
Media scanner runs as part of the boot sequence so that's why it works after reboot.
Because your gallery DB isn't updated.
You can run media scanner manually
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
or Use
MediaStore.Images.Media.insertImage();
You can also insert gallery(media) DB by hand.
private Uri insertMediaStore(String dirPath, String filename, byte[] jpegByteArray) {
String filePath = dirPath + "/" + filename;
try {
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN, new Date().getTime());
values.put(Images.Media.ORIENTATION, "0");
String title = filename.replace(".jpg", "");
values.put(Images.Media.TITLE, title);
values.put(Images.Media.DISPLAY_NAME, filename);
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(Images.Media.SIZE, jpegByteArray.length);
values.put("_data", filePath);
Uri uri = getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
OutputStream os = getContentResolver().openOutputStream(uri);
os.write(jpegByteArray);
os.close();
Logger.info("MediaStore Inserted URI:" + uri.toString());
return uri;
} catch(Exception ex) {
Logger.error(ex, "Failed to save the Bitmap file. FilePath: %s", filePath);
}
return null;
}
code reference: http://helloworld.naver.com/helloworld/1819
I always found the following answer for my Question:
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
but it do not work on my System (Nexus4 Android 4. ...)
I can create a File and add it to the Media-DB whith this code
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(file);
mediaScanIntent.setData(contentUri);
context.sendBroadcast(mediaScanIntent);
Where "file" is the new image-file i want to add.
after deleting the File I try to refresch the gallery by
Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED);
Uri contentUri = Uri.parse("file://" + Environment.getExternalStorageDirectory());
intent.setData(contentUri);
context.sendBroadcast(intent);
or
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
but there are still empty placeholder in the Galery.
I do not know why?...
To be on the safe side I add too my Activity in the AndroidManifest.xml
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<data android:scheme="file" />
</intent-filter>
but the result is the same. Any idea to solve the problem?
After the KitKat you can't send the Intent to run the MediaScanner on whole device's storage, because it is a CPU I\O intensive task and if every single app that download an image or delete one, call that intent battery would drain easily, hence they have decided to block that operation. Here are your options:
Use the old way for pre-KitKat
Pass your filePath:
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
} else{
MediaScannerConnection.scanFile(mContext, filePath, null, new MediaScannerConnection.OnScanCompletedListener() {
/*
* (non-Javadoc)
* #see android.media.MediaScannerConnection.OnScanCompletedListener#onScanCompleted(java.lang.String, android.net.Uri)
*/
public void onScanCompleted(String path, Uri uri)
{
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
A more reliable approach is to update the MediaStore directly:
// Set up the projection (we only need the ID)
String[] projection = { MediaStore.Images.Media._ID };
// Match on the file path
String selection = MediaStore.Images.Media.DATA + " = ?";
String[] selectionArgs = new String[] { file.getAbsolutePath() };
// Query for the ID of the media matching the file path
Uri queryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver contentResolver = getContentResolver();
Cursor c = contentResolver.query(queryUri, projection, selection, selectionArgs, null);
if (c.moveToFirst()) {
// We found the ID. Deleting the item via the content provider will also remove the file
long id = c.getLong(c.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
Uri deleteUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
contentResolver.delete(deleteUri, null, null);
} else {
// File not found in media store DB
}
c.close();
Check below code snippet to verify all the cases for add/delete/move image file programmatically and intimate the gallery app to refresh the data
/***
* Refresh Gallery after add image file programmatically
* Refresh Gallery after move image file programmatically
* Refresh Gallery after delete image file programmatically
*
* #param fileUri : Image file path which add/move/delete from physical location
*/
public void refreshGallery(String fileUri) {
// Convert to file Object
File file = new File(fileUri);
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
// Write Kitkat version specific code for add entry to gallery database
// Check for file existence
if (file.exists()) {
// Add / Move File
Intent mediaScanIntent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(new File(fileUri));
mediaScanIntent.setData(contentUri);
BaseApplication.appContext.sendBroadcast(mediaScanIntent);
} else {
// Delete File
try {
BaseApplication.appContext.getContentResolver().delete(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
MediaStore.Images.Media.DATA + "='"
+ new File(fileUri).getPath() + "'", null);
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
BaseApplication.appContext.sendBroadcast(new Intent(
Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
+ getBaseFolder().getAbsolutePath())));
}
}
For Xamarin C# you can Use following Code!
Just pass the full File path to the Array
Android.Media.MediaScannerConnection.ScanFile(Android.App.Application.Context, new string[] { deletedImageFilePath}, null, null);
I am trying to save an image from my application to the default gallery of my phone. The code below works perfectly if I have a SD card on the phone. The image saved appears in the phone's gallery and everything, as expected:
private Uri saveMediaEntry(File f, String title, String description, int orientation, Location loc) {
ContentValues v = new ContentValues();
v.put(Images.Media.TITLE, title);
v.put(Images.Media.DISPLAY_NAME, title);
v.put(Images.Media.DESCRIPTION, description);
v.put(Images.Media.ORIENTATION, orientation);
String nameFile = f.getName();
File parent = f.getParentFile() ;
String path = parent.toString().toLowerCase() ;
String nameParent = parent.getName().toLowerCase() ;
v.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
v.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, nameParent);
v.put(Images.Media.SIZE,f.length()) ;
if( nameFile.toLowerCase().contains(".png") ){
v.put(Images.Media.MIME_TYPE, "image/png");
}else if( nameFile.toLowerCase().contains(".jpg") ||
nameFile.toLowerCase().contains(".jpeg") ){
v.put(Images.Media.MIME_TYPE, "image/jpeg");
}else{
v.put(Images.Media.MIME_TYPE, "image/jpeg");
}
String imagePath = f.getAbsolutePath();
v.put("_data", imagePath) ;
ContentResolver c = getContentResolver() ;
Uri uriOfSucessfulySavedImage = null;
uriOfSucessfulySavedImage = c.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, v);
return uriOfSucessfulySavedImage;
}
However, if I try to save the same image into the internal storage (for when the phone does not have a SD card), the image does not appear in the phone's gallery! To try to do that, I only change one line from the above code:
uriOfSucessfulySavedImage = c.insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, v);
The interesting thing about this, however, is that the variable uriOfSucessfulySavedImage is not null (it returns content://media/internal/images/media/x, where 'x' is a number). So, the image is being saved somewhere in the internal storage of the phone, but it is not getting displayed in the phone gallery's as when I use MediaStore.Images.Media.EXTERNAL_CONTENT_URI.
Does anybody have any clue what is going on? How can I save an image into the internal storage of the phone and have that image in the phone's gallery?
Update
I forgot one important information. The File "f" in the parameters of the method "saveMediaEntry" is coming from this other method for when the SD card is mounted (that is, for the first code):
public static File getCacheDirectory(String desiredNameOfTheDirectory){
File fileCacheDir = null;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ){
fileCacheDir = new File( Environment.getExternalStorageDirectory(), desiredNameOfTheDirectory );
}
if(!fileCacheDir.exists()){
fileCacheDir.mkdirs();
}
return fileCacheDir;
}
and from the following code for when the SD card is not founded:
public static File getCacheDirectory(String desiredNameOfTheDirectory, Context context){
File fileCacheDir = null;
fileCacheDir = context.getCacheDir();
if(!fileCacheDir.exists()){
fileCacheDir.mkdirs();
}
return fileCacheDir;
}
Another easy way to do it. Add this after saving your file.
File imageFile = ...
MediaScannerConnection.scanFile(this, new String[] { imageFile.getPath() }, new String[] { "image/jpeg" }, null);
I haven't tried this, but I believe you need to run the Media Scanner to scan the internal storage directory so that the gallery can see your newly saved image. Check this post here.
Copy Past this Function in your Activity
private void scanner(String path) {
MediaScannerConnection.scanFile(FrameActivity.this,
new String[] { path }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("TAG", "Finished scanning " + path);
}
});
}
And then add this Line where you save your image
scanner(imageFile.getAbsolutePath());
Try this.
Write down this line once image stored in gallery.
File file = ..... // Save file
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
} else {
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
}
I've added an inserted in Gallery using android API as following:
Images.Media.insertImage(ctx.getContentResolver(),
"scard/test.jpg", "Hello" ,
"description");
Actually the image that I passed its full path (scard/test.jpg) is already successfully inserted in the DB, but when you open the gallery you can't see it unless you switch off/on the device or Mount/Unmount the external memory.
It there any way to refresh the gallery on demand?
Thanks
Bassel Kh.
I encountered this problem recently, I tried #Samuh's solution, but not works perfectly until I found the solution from Google's example:
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,
new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
I tried myself and worked flawlessly.
Or, similarly, you might want to take a look at the reference of the MediaScanner Class and someone on StackOverflow asked this question before:
Image, saved to sdcard, doesn't appear in Android's Gallery app
The solution using the Media Scanner (sendBroadcast). But, probably, on sdcards with a lot of pics and data, this operation should reach a high processing cost.
There is another solution, after saving your media file on gallery, you should notify the gallery DB that another file was inserted. That can be done like that:
private void addImageGallery( File file ) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); // or image/png
getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
This code doesn't save your media file to gallery, only saves the information about a new file in the gallery DB. You should store real file before.
This solution is faster because the gallery will not be fully re-scanned. But is not so trustful because all the information about the file was added manually.
static public boolean resetExternalStorageMedia(Context context) {
if (Environment.isExternalStorageEmulated())
return (false);
Uri uri = Uri.parse("file://" + Environment.getExternalStorageDirectory());
Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, uri);
context.sendBroadcast(intent);
return (true);
}
static public void notifyMediaScannerService(Context context, String path) {
MediaScannerConnection.scanFile(context,
new String[] { path }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
You can use this for refresh Android Gallery:
public void refreshAndroidGallery(Uri fileUri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Intent mediaScanIntent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(fileUri);
mContext.sendBroadcast(mediaScanIntent);
} else {
mContext.sendBroadcast(new Intent(
Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}
}
i tied everything then I found this perfect solution!
You can apply this method for any file type (jpg, png,pdf, etc)
public void refreshGallery(File f) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Intent mediaScanIntent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri fileUri = Uri.fromFile(f); //out is your output file
mediaScanIntent.setData(fileUri);
sendBroadcast(mediaScanIntent);
} else {
sendBroadcast(new Intent(
Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}
}
then
refreshGallery(newFileName);
newFIleName is a file path you can get your file path as
File newFileName = new File(filePath + "/" + fileName + ".jpg");
So our app has the option to take either a picture or a video. If the user takes a picture, we can use the MediaStore.Images.Media.insertImage function to add the new image (via a filepath) to the phone's gallery and generate a content:// style URI. Is there a similar process for a captured video, given that we only have it's filepath?
Here is an easy 'single file based solution':
Whenever you add a file, let MediaStore Content Provider knows about it using
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageAdded)));
Main advantage: work with any mime type supported by MediaStore
Whenever you delete a file, let MediaStore Content Provider knows about it using
getContentResolver().delete(uri, null, null)
I'm also interested, could you find a solution?
Edit: solution is RTFM. Based on the "Content Providers" chapter here is my code that worked:
// Save the name and description of a video in a ContentValues map.
ContentValues values = new ContentValues(2);
values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
// values.put(MediaStore.Video.Media.DATA, f.getAbsolutePath());
// Add a new record (identified by uri) without the video, but with the values just set.
Uri uri = getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
// Now get a handle to the file for that record, and save the data into it.
try {
InputStream is = new FileInputStream(f);
OutputStream os = getContentResolver().openOutputStream(uri);
byte[] buffer = new byte[4096]; // tweaking this number may increase performance
int len;
while ((len = is.read(buffer)) != -1){
os.write(buffer, 0, len);
}
os.flush();
is.close();
os.close();
} catch (Exception e) {
Log.e(TAG, "exception while writing video: ", e);
}
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
If your app is generating a new video and you simply want to give the MediaStore some metadata for it, you can build on this function:
public Uri addVideo(File videoFile) {
ContentValues values = new ContentValues(3);
values.put(MediaStore.Video.Media.TITLE, "My video title");
values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
values.put(MediaStore.Video.Media.DATA, videoFile.getAbsolutePath());
return getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
}
EDIT: As of Android 4.4 (KitKat), this method no longer works.
I was unable to get the Intent.ACTION_MEDIA_SCANNER_SCAN_FILE broadcast to work for me under API 21 (Lollipop), but the MediaScannerConnection does work, e.g.:
MediaScannerConnection.scanFile(
context, new String[] { path }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.d(TAG, "Finished scanning " + path + " New row: " + uri);
}
} );
Try this code. It seems working for me.
filePath = myfile.getAbsolutePath();
ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
Example of filePath -
/storage/emulated/0/DCIM/Camera/VID_20140313_114321.mp4