I was searching a bit on how to add images using the mediastore since I'm currently doing it manual with
final String myBitmap = "MyImage_"+ mFileDate + ".png";
File fileNumber = new File(APP_FILE_PATH, myBitmap);
out = new FileOutputStream( fileNumber );
final Bitmap mBitmap =getBitmap();
mBitmap.compress( Bitmap.CompressFormat.PNG, 85, out );
out.flush();
however I need the IDs that media manager uses to store since its easier to manage id rather than paths and such.
I tried adding it this way:
ContentValues values = new ContentValues();
values.put(Images.Media.TITLE, mFileName.getName());
values.put(Images.Media.DESCRIPTION, getString(R.string.bitdraw_description));
values.put(Images.Media.MIME_TYPE, "image/png");
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
out = getContentResolver().openOutputStream(uri);
mBitmap.compress( Bitmap.CompressFormat.PNG, 85, out );
out.flush();
however this adds the image to the folder where the photos are saved and not to the specific folder I want to.
Also tried this after the manual (first part):
Media.insertImage(getContentResolver(), mFileName.getPath(), mFileName.getName(), getString(R.string.description));
but this only generates duplicates since the image was saved first by the outputStream
A workaround I found on a thread here is to call a broadcast like this:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file://"+ Environment.getExternalStorageDirectory())));
but this is rather inneficient and takes long, and I want it to be the fastest, and I'm quite unsure if this actually generates the IDs, and if it does, how could I make this to scan only a specific folder in the SD ??
Any help would be appreciated.
Related
Hi I am new to android development and have been trying to accomplish the above said functionality.
I am testing app on Android 9, API 28. I am able to save captured image to folder but not been able to display it in gallery (Like WhatsApp).
I have tried:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
OutputStream os;
String[] split = imagePathNew.split("\\.");
ContentResolver resolver = context.getContentResolver();
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, split[0] + ".jpg");
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + File.separator + "Test");
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
os = (OutputStream) resolver.openOutputStream(Objects.requireNonNull(imageUri)); // imageLocalUri is the uri of captured image in folder
Bitmap bitmap = MediaStore.Images.Media.getBitmap(resolver, imageLocalUri);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
Objects.requireNonNull(os);
} else {
Intent updateInGallery = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
updateInGallery.setData(imageLocalUri); // imageLocalUri is the uri of captured image in folder
context.sendBroadcast(updateInGallery);
}
Can someone please help me with what am I doing wrong here?
Nothing is wrong with the posted code.
In the addition use following class
https://developer.android.com/reference/android/media/MediaScannerConnection#scanFile(java.lang.String,%20java.lang.String)
From docs
provides a way for applications to pass a newly created or downloaded media file to the media scanner service. The media scanner service will read metadata from the file and add the file to the media content provider.
While this code successfully creates an image that is also present in the phone's gallery, the extension is '.jpg' instead of '.gif'.
File gifFile; // gif file stored in Context.getFilesDir()
final ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "Image" + System.currentTimeMillis());
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/gif");
// Create a new gif image using MediaStore
final Uri gifContentUri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
// Open a writable stream pointing to the new file created by MediaStore
OutputStream outputStream = context.getContentResolver().openOutputStream(gifContentUri, "w");
// Copy the original file from the app private data folder to the file created by MediaStore
IOUtils.copyFile(new FileInputStream(gifFile), outputStream);
Output file is created inside Pictures folder by MediaStore. If I manually change the output file's extension to gif, the gif animation is playing inside Android gallery.
I feel I'm missing a small detail for this to work
Removed the DISPLAY_NAME line.
Add contentValues.put(MediaStore.MediaColumns.DATA, "/storage/emulated/0/Pictures/Image." + System.currentTimeMillis() + ".gif");
It goes to a subdir of the Pictures directory if the subdir exists contentValues.put(MediaStore.MediaColumns.DATA, "/storage/emulated/0/Pictures/Mine/Image." + System.currentTimeMillis() + ".gif");.
For Android Q the DATA column is useless.
String displayName = "Image." + System.currentTimeMillis() + ".gif";
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, displayName);
will do it there.
My users make custom images on my app and I am unsure what directory I should use when they save. Should I use MediaStore.Images.Media.EXTERNAL_CONTENT_URI?
Basically MediaStore.Images.Media.EXTERNAL_CONTENT_URI is part of Content Resolver which allow you to read and write resource from your user device. You need to ask yourself wether it is good to save their image into device. You could save your image in private or public which still decided by you. There is internal and external storage, wether you need all image to be deleted when your app is deleted or you don't want other app access the photo you user created use internal storage otherwise use external storage.Take a look on this link which take you step by step to understand why, which,how to save file into your app.
You can make a directory of your own app in the internal storage of the device and store all the pictures made from your app there.
You can make the directory using
File directory = new File(Environment.getExternalStorageDirectory() + File.separator + "<app name>");
if(!directory.exists){
directory.mkdirs;
}
And then store the pictures in this path
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String name = "<image name>"+n+".jpg";
File pictureFile = new File(directory, name);
pictureFile.createNewFile();
try {
FileOutputStream out = new FileOutputStream(pictureFile);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
Can anyone share code (or point me to Android sample code) to help me add images to an album in the Media Store (Gallery).
In my app I download images from our server, and also take new images using the camera (via Intent).
I would like to organize those images in an app-specific album, similar to what the Facebook (and other apps) app does, keeping related images all neatly organized.
I looked into this a while ago, following the Media Store API docs, and it didn't work for me....so need some help.
Thanks
This is a method used to store an image in the public Picture folder, with a custom app folder in it.
public void saveImageToExternal(String imgName, Bitmap bm) throws IOException {
//Create Path to save Image
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES+appFolder); //Creates app specific folder
path.mkdirs();
File imageFile = new File(path, imgName+".png"); // Imagename.png
FileOutputStream out = new FileOutputStream(imageFile);
try{
bm.compress(Bitmap.CompressFormat.PNG, 100, out); // Compress Image
out.flush();
out.close();
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(context,new String[] { imageFile.getAbsolutePath() }, null,new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
} catch(Exception e) {
throw new IOException();
}
}
you can use:
MediaStore.Images.Media.insertImage(ContentResolver cr, Bitmap source, String title, String description);
and I'm sure that somewhere here http://developer.android.com/guide/ in some of the sub-menus shows a command asking the MediaStore to scan a determined folder, I just can't find it now.
edit:
found it:
MediaScannerConnection.scanFile(Context context, String[] path, null, null);
Here is the code I ended up using to do this:
public static Uri addToTouchActiveAlbum( Context context, String title, String filePath ) {
ContentValues values = new ContentValues();
values.put( Media.TITLE, title );
values.put( Images.Media.DATE_TAKEN, System.currentTimeMillis() );
values.put( Images.Media.BUCKET_ID, filePath.hashCode() );
values.put( Images.Media.BUCKET_DISPLAY_NAME, Constants.TA_PHOTO_ALBUM_NAME );
values.put( Images.Media.MIME_TYPE, "image/jpeg" );
values.put( Media.DESCRIPTION, context.getResources().getString( R.string.product_image_description ) );
values.put( MediaStore.MediaColumns.DATA, filePath );
Uri uri = context.getContentResolver().insert( Media.EXTERNAL_CONTENT_URI , values );
return uri;
}
It works for the Images I have in "getExternalStorage()" (/storage/sdcard0)
I'd also like to add images I have in a different folder (a cacheDir I create under the folder returned by Context.getExternalCacheDir()). Problem: I don't know their mime-type (does that matter?), the folder is a different one in a different location with a different name - and I can't figure out how to add to an "album" per se.....as the album name seems to come from the folder name....
Or to put it another way:
values.put( Images.Media.BUCKET_DISPLAY_NAME, Constants.TA_PHOTO_ALBUM_NAME );
doesn't seem to have any effect?
I used this code snippet:
ContentValues image = new ContentValues();
image.put(Images.Media.TITLE, "ImageTitle");
image.put(Images.Media.DISPLAY_NAME, "Heart");
image.put(Images.Media.DESCRIPTION, "Heart");
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("_data", imageFile.getAbsolutePath());
getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
I create the image inside the cache directory of my application. I assume that the image is not copied into the media folder by the media provider and therefore not accessible from the media gallery application. Is it possible to add an image to the media gallery without writing the file to the mass storage of the phone?
I think that the answer you are looking for is described here. The second part of that section describes saving images. The gist of it appears to be that you first insert the ContentValues object into the content resolver, which returns a Uri object that the ContentResolver is willing to turn into an OutputStream for you that you can write the image to. The link provided includes the actual code you would need to do that.