I have a method to start the camera and take a photo (working with API 24 and Higher) :
public void invokeCamera()
{
// create the image Uri
Uri pictureUri = FileProvider.getUriForFile(getContext(),getContext().getPackageName() + ".provider",createImageFile());
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// tell the camera where to save
intent.putExtra(MediaStore.EXTRA_OUTPUT,pictureUri);
// permission for saving the image
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(intent,CAPTURE_REQ_CODE);
}
creating the image File:
private File createImageFile() {
File picturesDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String imgName = "myImageName_0X0Y02_test.jpg";
return new File(picturesDirectory.getPath(),"picture" + imgName );
}
the problem is :
this code is working without errors but sometimes i can't see the image in the Gallery , sometimes when i open the gallery after about 10 mins i see it there ! this is weird and i'm confused , am i missing something ?
All permissions are granted (Camera and full access to Storage)
Since you work with API 24 and higher, I will provide the code for it only. Basically, you need to tell the media scanner that a file was added so it can scan and add it straight away:
public static void scanMediaForChanges(Context context, File file){
MediaScannerConnection.scanFile(context,
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);
}
});
}
You are number #### with this problem. You should tell the media store about your new file.
To do that invoke the media scanner for your file.
Code has been posted a ### times. So google.
Related
I am saving a video to public folder using
private File createVideoFile(){
if(!isExternalStorageWritable()){
return null;
}
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), "vid121.mp4");
return file;
}
However I tried also PICTURES, and VIDEOS
and no matter what folder I try, the video does not appear when the user opens default gallery app (or even any app that shows videos). I navigated to the folder through Files app and I can see the video.
How can I make sure the video appears as part of gallery?
Thank you
You need to rescan gallery. Because Gallery refreshed by default at boot time.
Try this.
// 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 hope someone can help me with this problem.
I have an app which enables the user to take a video (.mp4) or pick existing one. If taking a video, the video is saved to a public directory and I triggered the Android to scan the file to add it to media gallery.
Problem is, taking the video is working fine, I can preview the finished video just fine in my app. But this same video won't appear in media gallery and won't be accessible by other apps -except the FileManager-, even though other .mp4 in the same folder appear in the list just fine.
Further info:
In FileManager app, The not-appearing files have icon video icon while the appearing ones got a thumbnail. I can trigger these not-appearing files to be added to media gallery apps by cut and paste the files in FileManager app (so I believe is not due to files being corrupted).
The scan code works fine for the my code that take images from existing camera app, it just won't work for the video ones...
Is there any need for additional permission for this to work? I've added/asked/request permission for write and read from ext. storage and camera in my manifest and code.
This below is how I take the Video and scan it into gallery :
private void takeVideo() {
Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if (takeVideoIntent.resolveActivity(ctx.getPackageManager()) != null) {
// Create the file where photo should go
File mediaFile = null;
try {
mediaFile = getOutputMediaFile(ctx, MEDIA_TYPE_VIDEO);
} catch (IOException ex) {
Log.e("FragCamera", "takeVideo() : Error occurred while creating File." + ex);
}
if (mediaFile != null) {
Uri mediaUri = Uri.fromFile(mediaFile);
Log.d("FragCamera", "takeVideo() mediaUri: " + mediaUri);
currMediaUri = mediaUri;
currPhotoPath = mediaFile.getAbsolutePath();
Log.d("FragCamera", "takeVideo() currPhotoPath: " + currPhotoPath);
//make the new file available for other apps
updateMediaGallery(mediaFile);
MediaScannerConnection.scanFile(
ctx,
new String[]{currPhotoPath},
new String[]{"video/mp4"},
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
Log.v("FragCameraScan",
"file " + path + " was scanned seccessfully: " + uri);
}
});
takeVideoIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mediaUri);
this.startActivityForResult(takeVideoIntent, I_REQUEST_VIDEO_CAPTURE);
}
}
}
private void galleryAddPic(String filePath) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(filePath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
ctx.sendBroadcast(mediaScanIntent);
}
Logcat value for each Log in the code above :
D/FragCamera: takeVideo() mediaUri: file:///storage/emulated/0/DCIM/Camera/VID_20161207_142021.mp4
D/FragCamera: takeVideo() currPhotoPath: /storage/emulated/0/DCIM/Camera/VID_20161207_142021.mp4
V/FragCameraScan: file /storage/emulated/0/DCIM/Camera/VID_20161207_142021.mp4 was scanned seccessfully: null
try using 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);
}
the 'values' is simply meta data about the video
case R.id.menu_delete:
File photoToDelete = new File(photoPath, photoList[gPosition]);
photoToDelete.delete();
checkPhotoFolder();
galleryAdapter.notifyDataSetChanged();
Log.d("position", "" + gPosition);
return true;
I'm manually delete a photo file using above code. But in the system gallery the photo still show the blank thumbnail.
The question is how can I delete the photo file and also the thumbnail of it in the gallery?
Try invoke the MediaScanner to refresh the gallery
// 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);
}
});
Code from Google's example
Try this.
getContentResolver().delete(Uri.fromFile(photoToDelete), null, null);
You must update the data structure (eg. list or array) that stores the photos.
I guess it is photoList.
So you should do (assuming photoList is an array):
photoList = photoList.asList().remove(gPosition).toArray();
I'm deleting a file as such
File fileToDelete = new File("filepath");
Boolean fileDeleted = fileToDelete.delete();
The fileDeleted is true and when I check the DDMS the file is not there but if I click on the gallery it still shows the image that was just deleted. I have to restart the emulator to see the change.
Is there any way to see the changes without having to restart the emaulator? I'm using eclipse
The gallery is using Android's media database to display the list of media. Deleting the file will not be reflected in the database until it scans the filesystem again. That is for example done after rebooting.
You can either delete the file directly through the database or force it to scan the file or folder you just deleted.
File fileToDelete = new File("filepath");
boolean fileDeleted = fileToDelete.delete();
// request scan
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(fileToDelete));
sendBroadcast(scanIntent);
It is to do with how Gallery shows the Image files. Image file's Thumbnails are cached in the MediaStore and all the details are present in the Mediastore contentProvider.
Deleting the file will not update this database. But when you restart the emulator, Mediascanning is done by android. If MediaScanning can be triggered , gallery will stop showing the files
I use the following code (which is also much like my code for creating a video which also tells the media system about file changes and correctly updates the Gallery):
private void deleteVideo(String videoUrl)
{
File videoFile = new File(videoUrl);
if (!videoFile.delete())
{
Log.e(TAG, "Failed to delete " + videoUrl);
}
else
{
MediaScannerConnection.scanFile(mContext,new String[] { videoUrl }, null, new MediaScannerConnection.OnScanCompletedListener()
{
public void onScanCompleted(String path, Uri uri)
{
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
}
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");