My app is able to take a photo and stores it into a specified folder.
Using ES File explorer, I'm able to confirm that the image has been stored in sd card and the specified folder.
However, my gallery is not showing this album immediately. It will need to take quite some time. Is there any ways that i can make the detection immediate using codes?
The following broadcasting codes did not seem to work. My gallery doesnt immediately do a refresh to retrieve the newly created album and image.
Kindly assist. Thanks!
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".png");
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(mediaFile);
mediaScanIntent.setData(contentUri);
v.getContext().sendBroadcast(mediaScanIntent);
}
It might take some time till it finished the scanning.
If you wish, you can at least be notified when it finished:
MediaScannerConnection.scanFile(
getApplicationContext(),
new String[]{file.getAbsolutePath()},
null,
new OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
// file was scanned
}
});
for more information read here.
Related
So I am working on a project where if a manager registers a user he gets an email with a QR code (bitmap). The QR code is saved in cache. I want the QR code removed after the QR code is sent to the user, but a "cache" folder gets created (also shows up in gallery), and the image itself gets deleted but it remains there ( you cant see it, but its there as a grey square).
Any idea how to remove the created folder and the created bitmap compeletely?
My code:
BitmapSaver(Context mContext){
this.mContext=mContext;
this.cache = new DiskBasedCache(mContext.getCacheDir(), 1024 * 1024);
}
public static File saveImageToExternalStorage(Context context, Bitmap finalBitmap) {
destFolder =context.getCacheDir().getAbsolutePath();
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
// myDir = new File(root + "/saved_images");
// myDir.mkdirs();
long n = System.currentTimeMillis() / 1000L;
fname = "Image-" + n + ".jpg";
//file2 = new File(destFolder);
file = new File(destFolder+"/"+fname);
if (file.exists())
file.delete();
try {
Log.i("path",destFolder+"/"+fname);
FileOutputStream out = new FileOutputStream(destFolder+"/"+fname);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
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);
url = Uri.parse(path);
Log.i("External",url.toString());
}
});
return file;
}
In Activity after email is sent:
BitmapSaver bms = new BitmapSaver(RegisterActivity.this);
bms.saveImageToExternalStorage(RegisterActivity.this, bitmap);
bms.file.delete();
First of all you need to know what MediaScannerConnection.scanFile does. It will update the file information to the current device, so other applications like gallery, file explorer, etc, can show the correct file information and content.
From your code, when you are saving the temporary file, you are also scanning it, because your app has changed the corresponding file, which is creating the file to be exact. So the file will be available to the other applications right away. But, since the file location is in your application cache directory, it will not accessible by other applications. Usually you must restart your device to update the file information if you don't call MediaScanner.scanFile. If you are creating a temporary file, I think you don't need to call MediaScanner.scanFile, since you will delete it right away.
Then after delete, you also need to re-scan the file again, so other applications will know that the file has been deleted.
Also, despite of using MediaScannerConnection.scanFile directly, if you are supporting android version < KitKat, you should broadcast with intent action Intent.ACTION_MEDIA_MOUNTED instead. And I also recommend that you are broadcasting the data directly, because from my experience MediaScannerConnection.scanFile failed from one of my test devices.
Intent mediaScanIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(Uri.fromFile(new File(imagePath)));
} else {
Uri fileUri = Uri.parse("file://" + imagePath);
mediaScanIntent = new Intent(Intent.ACTION_MEDIA_MOUNTED, fileUri);
}
context.sendBroadcast(mediaScanIntent);
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.
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
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 want create a new 'album' in Android. I unserstood that you have to do it with your own ContentProvider. But i can't figure out how. If you take pictures, all the images appear in the album 'Camera'. If you have installed Google+ you'll see 2 extra albums: Instant Upload & Profile Picture.
We want to create something similar. We have an album per user online and we want that it appears as an album item in the Gallery app. Can someone point me in the right direction.
I already checked: http://developer.android.com/guide/topics/providers/content-providers.html
Actually im not really sure if it is possible.
You can use this way to create album in Gallery app. The name appears as 'app images'.
String path = Environment.getExternalStorageDirectory().toString();
File dir = new File(path, "/appname/media/app images/");
if (!dir.isDirectory()) {
dir.mkdirs();
}
File file = new File(dir, filename + ".jpg");
String imagePath = file.getAbsolutePath();
//scan the image so show up in album
MediaScannerConnection.scanFile(this,
new String[] { imagePath }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
if(Config.LOG_DEBUG_ENABLED) {
Log.d(Config.LOGTAG, "scanned : " + path);
}
}
});