I need to save an image to camera folder, but as Android Q getExternalStoragePublicDirectory is deprecated, I do it in another way. What I have (this method receive bitmap and its name):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentResolver resolver = mContext.getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/" + IMAGES_FOLDER_NAME);
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OutputStream fos = resolver.openOutputStream(imageUri);
saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} else {
String imagesDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM).toString() + File.separator + IMAGES_FOLDER_NAME;
File file = new File(imagesDir);
if (!file.exists()) {
file.mkdir();
}
File image = new File(
imagesDir,
name + ".png"
);
final long fileHashCode = image.hashCode();
Logger.d(TAG, "saveImage, saving image file, hashCode = " + fileHashCode);
FileOutputStream fos = new FileOutputStream(image);
saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
}
That perfectly works for all needed OS versions, but it looks inaccurate and I'd like to find a more common way. I tried to play around with content values or try some similar way as for Q, but it doesn't work. I've seen many questions here, but neither of them can help me.
The question is how can I optimize saving for OS lower than Q?
Touch and hold the image. Select a save option (e.g., Save attachment, Save to SD card, etc.). Unless otherwise specified, the image is saved to the default picture/video location (e.g., Gallery, Photos, etc.).
You can use below code to get all images from specific folder. 1) First you need to define File object to get the storage and appened the name of the folder you want to read. File folder = new File(Environment. getExternalStorageDirectory().
The most generalized version I was able to write is:
private Uri saveImage(Context context, Bitmap bitmap, @NonNull String folderName, @NonNull String fileName) throws IOException {
OutputStream fos = null;
File imageFile = null;
Uri imageUri = null;
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentResolver resolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
contentValues.put(
MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + File.separator + folderName);
imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
if (imageUri == null)
throw new IOException("Failed to create new MediaStore record.");
fos = resolver.openOutputStream(imageUri);
} else {
File imagesDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).toString() + File.separator + folderName);
if (!imagesDir.exists())
imagesDir.mkdir();
imageFile = new File(imagesDir, fileName + ".png");
fos = new FileOutputStream(imageFile);
}
if (!bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos))
throw new IOException("Failed to save bitmap.");
fos.flush();
} finally {
if (fos != null)
fos.close();
}
if (imageFile != null) {//pre Q
MediaScannerConnection.scanFile(context, new String[]{imageFile.toString()}, null, null);
imageUri = Uri.fromFile(imageFile);
}
return imageUri;
}
If you've found a better way, post here, I'll mark it as answer.
Using this document : https://developer.android.com/training/data-storage
Create temp file first
val mTempFileRandom = Random()
fun createTempFile(ext:String, context:Context):String {
val path = File(context.getExternalCacheDir(), "AppFolderName")
if (!path.exists() && !path.mkdirs())
{
path = context.getExternalCacheDir()
}
val result:File
do
{
val value = Math.abs(mTempFileRandom.nextInt())
result = File(path, "AppFolderName-" + value + "-" + ext)
}
while (result.exists())
return result.getAbsolutePath()
}
Send file from path
copyFileToDownloads(this@CameraNewActivity, File(savedUri.path))
Copy data to storage
MAIN_DIR: Main folder name in which you want to store image (Like App Name) IMAGE_DIR: Sub folder if you want to create.
fun copyFileToDownloads(context: Context, downloadedFile: File): Uri? {
// Create an image file name
val timeStamp = SimpleDateFormat(DATE_FORMAT_SAVE_IMAGE).format(Date())
val imageFileName = "JPEG_$timeStamp.jpg"
val resolver = context.contentResolver
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, imageFileName)
put(MediaStore.Images.Media.MIME_TYPE, IMAGE_MIME_TYPE)
put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + MAIN_DIR + File.separator + IMAGE_DIR + File.separator)
}
resolver.run {
val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
uri
}
} else {
val authority = "${context.packageName}.provider"
val imagePath =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)?.absolutePath
val destinyFile = File(imagePath, imageFileName)
val uri = FileProvider.getUriForFile(context, authority, destinyFile)
FileUtils.scanFile(context, destinyFile.absolutePath)
uri
}?.also { uri ->
var writtenValue = 0L
// Opening an outputstream with the Uri that we got
resolver.openOutputStream(uri)?.use { outputStream ->
downloadedFile.inputStream().use { inputStream ->
writtenValue = inputStream.copyTo(outputStream)
Log.d("Copy Written flag", " = $writtenValue")
}
}
}
}
ScanFile : ( More detail : https://developer.android.com/reference/android/media/MediaScannerConnection )
fun scanFile(context:Context, path:String) {
MediaScannerConnection.scanFile(context,
arrayOf<String>(path), null,
{ newPath, uri-> if (BuildConfig.DEBUG)
Log.e("TAG", "Finished scanning " + newPath) })
}
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