If this is something you are interested in, you can use MediaStore
to programmatically save in the gallery a picture from your internal storage.
Code
You could use the following code, which I successfully use in my app.
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "MyPicture.jpg");
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
}
ContentResolver resolver = myContext.getContentResolver();
Bitmap bitmap;
Uri uri;
try {
// Requires permission WRITE_EXTERNAL_STORAGE
bitmap = BitmapFactory.decodeFile(currentPhotoPath);
uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
} catch (Exception e) {
Log.e(LOG_TAG, "Error inserting picture in MediaStore: " + e.getMessage());
return;
}
try (OutputStream stream = resolver.openOutputStream(uri)) {
if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream) {
throw new IOException("Error compressing the picture.");
}
} catch (Exception e) {
if (uri != null) {
resolver.delete(uri, null, null);
}
Log.e(LOG_TAG, "Error adding picture to gallery: " + e.getMessage());
}
Credits to this answer for the conversion of File
to Bitmap
and to this answer for the usage of MediaStore
.
Notes
BitmapFactory.decodeFile()
requires the runtime permission WRITE_EXTERNAL_STORAGE
- With the introduction of scoped memory in Android 10 (which will become mandatory in Android 11, see this article)
MediaStore
is probably the only reliable way to save pictures to the gallery
- A consequence of scoped storage is that, yes, you should keep using the internal storage for the cache copy of your picture.
Tests
I have tested this code with with targetSdkVersion
29 on the following devices / OS combinations
- Samsung Galaxy S10 / API 29
- Samsung Galaxy S9 / API 29
- Huawei Nexus 6P / API 27