我正在创建一个简单的图像编辑器应用程序,因此需要加载和保存图像文件。我希望保存的文件出现在一个单独的相册画廊。从Android 28到29,应用程序能够访问存储的程度发生了巨大的变化。我可以在Android (API 29)中做我想做的事情,但是这种方式并不是向后兼容的。
当我想在较低的API版本中获得相同的结果时,到目前为止,我只找到了方法,这需要使用废弃的代码(从API 29开始)。
其中包括:
MediaStore.Images.Media.DATA列的使用Environment.getExternalStoragePublicDirectory(...)获取到外部存储的文件路径MediaStore.Images.Media.insertImage(...)直接插入图像我的问题是:是否有可能以这种方式实现它,因此它是向后兼容的,但不需要被弃用的代码?如果没有,在这种情况下使用不推荐的代码可以吗?或者这些方法会很快从sdk中删除吗?在任何情况下,使用不推荐的方法感觉都很糟糕,所以我宁愿不使用:)
这就是我发现的使用API 29的方法:
ContentValues values = new ContentValues();
String filename = System.currentTimeMillis() + ".jpg";
values.put(MediaStore.Images.Media.TITLE, filename);
values.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.RELATIVE_PATH, "PATH/TO/ALBUM");
getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values);然后使用insert方法返回的URI保存位图。问题是RELATIVE_PATH字段是在API 29中引入的,所以当我在较低版本上运行代码时,图像会被放入"Pictures“文件夹,而不是”PATH/TO/相册“文件夹。
发布于 2019-07-22 11:36:13
在这种情况下使用不推荐的代码可以吗?或者这些方法会很快从sdk中删除吗?
DATA选项不会在Android上工作,因为这些数据不包含在query()结果中,即使您请求它,也不能使用它返回的路径,即使它们被返回。
默认情况下,Environment.getExternalStoragePublicDirectory(...)选项不会在Android上工作,尽管您可以添加一个清单条目来重新启用它。但是,这个清单条目可能会在Android中被删除,所以除非你时间短,否则我不会走这条路。
AFAIK,MediaStore.Images.Media.insertImage(...)仍然工作,尽管它被废弃了。
是否有可能以这种方式实现它,因此它是向后兼容的,但不需要不推荐的代码?
我的猜测是,您需要使用两种不同的存储策略,一种用于API级别的29+,另一种用于旧设备。我在这个示例应用程序中采用了这种方法,尽管在那里我正在处理视频内容,而不是图像,所以insertImage()不是一种选择。
发布于 2020-06-26 19:05:16
这是对我有用的代码。此代码将图像保存到电话上的子目录文件夹中。它检查android版本的手机,如果它高于android,它运行所需的代码,如果它在下面运行代码,它将运行code语句中的代码。
来源:https://androidnoon.com/save-file-in-android-10-and-below-using-scoped-storage-in-android-studio/
private void saveImageToStorage(Bitmap bitmap) throws IOException {
OutputStream imageOutStream;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME,
"image_screenshot.jpg");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.RELATIVE_PATH,
Environment.DIRECTORY_PICTURES + File.pathSeparator + "AppName");
Uri uri =
getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
imageOutStream = getContentResolver().openOutputStream(uri);
} else {
String imagesDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES). toString() + "/AppName";
File image = new File(imagesDir, "image_screenshot.jpg");
imageOutStream = new FileOutputStream(image);
}
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream);
imageOutStream.close();
}发布于 2020-09-22 19:31:02
对于旧API (<29),我将图像放入外部媒体目录并通过MediaScannerConnection进行扫描。
让我们看看我的密码。
此函数创建一个图像文件。注意一个appName变量--它是一个会显示图像的相册的名称。
override fun createImageFile(appName: String): File {
val dir = File(appContext.externalMediaDirs[0], appName)
if(!dir.exists()) {
ir.mkdir()
}
return File(dir, createFileName())
}然后,我将一个图像放到文件中,最后,我运行了这样一个媒体扫描仪:
private suspend fun scanNewFile(shot: File): Uri? {
return suspendCancellableCoroutine { continuation ->
MediaScannerConnection.scanFile(
appContext,
arrayOf<String>(shot.absolutePath),
arrayOf(imageMimeType)) { _, uri -> continuation.resume(uri)
}
}
}https://stackoverflow.com/questions/57030990
复制相似问题