I am currently creating a camera app and storing it. However, every time I take a picture, the picture is saved in the directory but is not saved in the Gallery. I think it's all about the generation of thumbnail right after the image has been taken. How can you generate a thumbnail in the gallery?
Try this:
Intent mediaScan = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScan.setData(uri);
context.sendBroadcast(mediaScan);
If you are adding files or images programmatically, you have to use MediaScannerClass to scan the media file for your sd card.
of you can also use following piece of code:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
I made an application that has as one of it's features file sharing, and the files sent may be anything. However, Images and Videos sent are not showing up on the default Gallery app using the com.androidquery.AQuery download. Is there a step I'm missing that would mark the file as media or something like that? Because I thought you only needed to mark file as NOT media on Android when you really don't want them to show.
After file downloading you need to execute
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");
getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
To register your file in android MediaStore where gallery takes data about stored media files
After some research based on Sone's answer, I got this code I needed to insert after the download:
Uri uri = Uri.fromFile(new File(downloadFilePath)); //Insert your file path here
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(uri);
getApplicationContext().sendBroadcast(mediaScanIntent);
As he said, I needed to register my file in android MediaStore, and this code does that no matter what type of media is downloaded by forcing the scanner to go over the recently downloaded file. Hope it helps anyone else needing this.
I am currently developing an Android Application where users take pictures which are stored in External Memory on the device then I am trying to also get the Gallery to scan the file to add the new media to the Gallery however this does not seem to update until the device reboots.
The code I am using is as follows:
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Log.v("INFO", mCurrentPhotoPath.toString());
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
After taking a picture with my app I can verify it exists using a file manager app on the device and also Logging the file path it appears to be correct before passing it to Media Scanner
file:/storage/emulated/0/Pictures/JPEG_20140712_163043_1418054327.jpg
Thanks Aaron
I managed to solve this. The issue was due to, where I setup the mCurrentPhotoPath. So I updated the code to use
photoFile = createImageFile();
mCurrentPhotoPath = photoFile.getAbsolutePath();
Media Scanner take some to scan and insert show results after calling sendBroadcast you can use MediaScannerConnection method onScanCompleted
and then check image in gallery.
for more reference follow Link
I have a Bitmap saved in the directory: Environment.getExternalStorageDirectory()+ File.separator + "Images" in a subdirectory. With a fileManager i can find the image and open it. But in the Gallery of the Smartphone i can't find the Image.
How can i get it there?
To be make you file known by the Gallery you need to call the MediaScanner:
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);
See also: https://www.grokkingandroid.com/adding-files-to-androids-media-library-using-the-mediascanner/
You can actually directly access the Pictures directory. To do this, use
getExternalStoragePublicDirectory(String type)
, where type is equal to Environment.DIRECTORY_PICTURES.
See http://developer.android.com/reference/android/os/Environment.html#getExternalStoragePublicDirectory%28java.lang.String%29 for more info.
That's cleaner than supposing that pictures are always stored in a directory called "Images"...
Now to force the Gallery to register the change, look at https://stackoverflow.com/a/15837638/2984973 .
To quote the answer, you want to broadcast an intent specifying your new picture, likewise:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(myNewFile)));
My app allows a user to save an image to their SD card. But I'm not sure how to make it appear in the gallery until you unmount and remount the SD card. I have googled for a couple of days with this problem but am not sure how to make it appear automatically. I found
this link but I'm not sure how to use the class. This is what i use to save the file. At the bottom of the try catch block is where I want to scan the sd card for new media.
FileOutputStream outStream = null;
File file = new File(dirPath, fileName);
try {
outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch {
...
}
If anyone could point me in the right direction, I would appreciate.
I've tried plenty of different methods to trigger the MediaScanner, and these are my results.
SendBroadcast
The most simple and naive solution. It consists in executing the following instruction from your code:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
However, this no longer works in KitKat devices, due to a lack of required permissions.
MediaScannerWrapper
As posted here (per #Brian's answer), it consists in wrapping a MediaScannerConnection instance in order to trigger the scan() method over a specific directory. This method has proven to be working fine for 4.3 and below, but still no luck with KitKat (4.4+).
FileWalker
One of the many Play Store apps that tries to overcome the MediaStore's lack of commitment to update its database is ReScan SD. It sends a lot of different broadcasts:
sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file://" + Environment.getExternalStorageDirectory())));
sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable")));
sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable/SD")));
sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable/MicroSD")));
sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///mnt/Removable/MicroSD")));
sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///mnt")));
sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///storage")));
sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable")));
and tries to support KitKat by manually triggering the scan() method over each file of the base directory. Unfortunately, this is both very CPU-intensive and time-consuming, so it is not very recommended.
"The shell way"
The only thing that seem to work with KitKat in some cases is sending the broadcast via adb shell. So, this snippet allows you to do just that programmatically:
Runtime.getRuntime().exec("am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://" + Environment.getExternalStorageDirectory());
It is more of an hack-ish way of doing it, but at the moment is the best I could come up with.
Bottom line
Each of the above solutions actually works for everything that is not KitKat. That's because, thanks to Justin, a bug has been found and issued to the official Tracker. This means that, until the bug is ironed out, we are left with no true KitKat support.
Which one to use? Among those, I would use the MediaScannerWrapper solution, together with the shell-ish approach (the last one).
Since the last answer I posted apparently wasn't an appropriate method, I found another method here. You basically create a wrapper class, initialize it, and then call the scan() method. Very helpful post. Let me know if this isn't appropriate either.
Use MediaScannerConnection:
http://developer.android.com/reference/android/media/MediaScannerConnection.html
It can be a little bit of a pain because of the multiple levels of asynchronous calls, so as of API 8 (Froyo) there is a helper function:
http://developer.android.com/reference/android/media/MediaScannerConnection.html#scanFile(android.content.Context, java.lang.String[], java.lang.String[], android.media.MediaScannerConnection.OnScanCompletedListener)
You could also call media scanner explicitly by sending broadcast.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri
.parse("file://"
+ Environment.getExternalStorageDirectory())));
Edit
This was an old post. Updating it to new versions
Android is taking steps to prevent apps from spoofing more system broadcasts like this.
If you want to tell Android to index a file you put on external storage, either use MediaScannerConnection or ACTION_MEDIA_SCANNER_SCAN_FILE
Reference: This post
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
final Uri contentUri = Uri.fromFile(outputFile);
scanIntent.setData(contentUri);
sendBroadcast(scanIntent);
} else {
final Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()));
sendBroadcast(intent);
}
If the above piece of code is not working you can try the following:
MediaScannerConnection.scanFile(this, new String[] {
file.getAbsolutePath()
}, null, new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
}
});
Here is another way to force scan:
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,"uri to file"));
And then system will fire ACTION_MEDIA_SCANNER_FINISHED broadcast so you can react on it with BroadcastReceiver
In order to be able to receive ACTION_MEDIA_SCANNER_FINISHED broadcast, intent filter should contain data scheme:
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_FINISHED);
intentFilter.addDataScheme("file");
context.registerReceiver(mMediaScannerFinishReceiver, intentFilter);
from the doc:
public static final String ACTION_MEDIA_SCANNER_SCAN_FILE
Added in API level 1 Broadcast Action: Request the media scanner to
scan a file and add it to the media database. The path to the file is
contained in the Intent.mData field.
and
public static final String ACTION_MEDIA_SCANNER_FINISHED
Added in API level 1 Broadcast Action: The media scanner has finished
scanning a directory. The path to the scanned directory is contained
in the Intent.mData field.
You can use MediaStore.Images.Media.insertImage to insert an item into the gallery.