I am trying to save a bitmap that is created by the user to the default 'Pictures' folder on the device. I will start with the option that seems to be the more common method:
public void saveImageToExternalStorage(String filename, Bitmap image) {
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
try {
File directory = new File(path);
if (!directory.exists()) {
directory.mkdirs();
}
File file = new File(directory, filename + ".jpeg");
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
This is supposed to save to the 'Pictures' folder, but Environment.getExternalStorageDirectory().getAbsolutePath()
seems to create a new file structure like this file://storage/emulated/11/Pictures/
and save the picture to that. I have also tried Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
with the same result. But this is not the default 'Pictures' folder on any of my test devices or emulators. Which led me to look for other methods, and I found this:
public void saveImageToExternalStorage(String filename, Bitmap image) {
try {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, filename);
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
Uri filepath = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
OutputStream outputStream = getContentResolver().openOutputStream(filepath);
image.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
This actually saves to the default file structure, which apparently looks like this: content://media/external/images/media/4282
. But there seems to be no way to specify the filename of the image (Media.TITLE
just sets the title attribute, not the actual filename), it saves as a (seemingly) random string of numbers. I looked at the API Guide for MediaStore.Images.Media
and there does not seem to be any other variable that would set the filename. This also does not seem to be the correct way of saving, according to the Android Developer Guides. I would like to know if there is any way of saving to this folder, while also setting my own filename. And if this method could produce unforeseen problems on other devices.
EDIT: For anyone interested this is my current code, based on the answer by @CommonsWare:
public void saveImageToExternalStorage(Context context, String filename, Bitmap image) throws IOException {
File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file = new File(directory, filename + ".jpeg");
FileOutputStream outputStream = new FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.getFD().sync();
outputStream.close();
MediaScannerConnection.scanFile(context, new String[] {file.getAbsolutePath()}, null, null);
}
This is supposed to save to the 'Pictures' folder
getExternalStorageDirectory()
returns the root of external storage, not some location inside of it (e.g., Pictures/
, DCIM/
, Movies/
).
I have also tried Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) with the same result
That will give you the proper directory, or whatever the device thinks the proper directory is (usually named Pictures/
in external storage for whoever the current user is).
but Environment.getExternalStorageDirectory().getAbsolutePath() seems to create a new file structure like this file://storage/emulated/11/Pictures/
The 11
is a bit unusual, and getAbsolutePath()
does not return something with a file://
scheme, but otherwise that seems about right.
But this is not the default 'Pictures' folder on any of my test devices or emulators.
I do not know how you have determined this.
I would like to know if there is any way of saving to this folder, while also setting my own filename.
Start with your first sample, switching to DIRECTORY_PICTURES
. Then:
have outputStream
be a FileOutputStream
call outputStream.getFD().sync()
after flush()
and before close()
use MediaScannerConnection
and its scanFile()
method to arrange for the MediaStore
to index the image, so it is available to on-device galleries, desktop OS file managers, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With