我正在研究从web服务器下载图像的功能,在屏幕上显示它,如果用户希望保持图像,将其保存在SD卡的某个文件夹中。有没有一种简单的方法来获取位图并将其保存到我选择的SD卡文件夹中?
我的问题是,我可以下载图像,在屏幕上显示为位图。我能够找到的将图像保存到特定文件夹的唯一方法是使用FileOutputStream,但这需要一个字节数组。我不知道如何转换(如果这是正确的方式)从位图到字节数组,所以我可以使用FileOutputStream写入数据。
我的另一个选择是使用MediaStore:
MediaStore.Images.Media.insertImage(getContentResolver(), bm,
barcodeNumber + ".jpg Card Image", barcodeNumber + ".jpg Card Image");
它可以很好地保存到SD卡,但不允许您自定义文件夹。
我知道这个问题很老了,但是现在我们可以在没有WRITE_EXTERNAL_STORAGE权限的情况下实现相同的结果。而不是我们可以使用文件提供程序。
private fun storeBitmap(bitmap: Bitmap, file: File){
requireContext().getUriForFile(file)?.run {
requireContext().contentResolver.openOutputStream(this)?.run {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, this)
close()
}
}
}
如何从提供者检索文件?
fun Context.getUriForFile(file: File): Uri? {
return FileProvider.getUriForFile(
this,
"$packageName.fileprovider",
file
)
}
另外,不要忘记在Android manifest中注册你的提供商
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
我发现发送PNG和透明度的方式。
String file_path = Environment.getExternalStorageDirectory().getAbsolutePath() +
"/CustomDir";
File dir = new File(file_path);
if(!dir.exists())
dir.mkdirs();
String format = new SimpleDateFormat("yyyyMMddHHmmss",
java.util.Locale.getDefault()).format(new Date());
File file = new File(dir, format + ".png");
FileOutputStream fOut;
try {
fOut = new FileOutputStream(file);
yourbitmap.compress(Bitmap.CompressFormat.PNG, 85, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("image/*");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
intent.putExtra(android.content.Intent.EXTRA_TEXT, "");
intent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(intent,"Sharing something")));
在Android 4.4 Kitkat之后,截至2017年,Android 4.4及以下的份额约为20%并且正在下降,使用File类和getExternalStorageDirectory()方法保存到SD卡是不可能的。这个方法返回你的设备内部内存和图像保存为每个应用程序可见。你也可以只保存你的应用程序私有的图像,当用户使用openFileOutput()方法删除你的应用程序时删除。
从Android 6.0开始,您可以将SD卡格式化为内部内存,但只能对您的设备私有。(如果你格式化SD车作为内部存储器,只有你的设备可以访问或看到它的内容)你可以使用其他答案保存到SD卡,但如果你想使用一个可移动的SD卡,你应该阅读下面我的回答。
您应该使用存储访问框架获取uri到activity的onActivityResult方法来获取用户选择的文件夹,并添加检索持久权限,以便用户重新启动设备后能够访问文件夹。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
// selectDirectory() invoked
if (requestCode == REQUEST_FOLDER_ACCESS) {
if (data.getData() != null) {
Uri treeUri = data.getData();
tvSAF.setText("Dir: " + data.getData().toString());
currentFolder = treeUri.toString();
saveCurrentFolderToPrefs();
// grantUriPermission(getPackageName(), treeUri,
// Intent.FLAG_GRANT_READ_URI_PERMISSION |
// Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
final int takeFlags = data.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(treeUri, takeFlags);
}
}
}
}
现在,保存保存文件夹到共享首选项,而不是每次你想保存图像时都要求用户选择文件夹。
你应该使用DocumentFile类来保存你的图像,而不是File或ParcelFileDescriptor,要了解更多信息,你可以检查这个线程保存图像到SD卡压缩(CompressFormat.JPEG, 100, out);方法和DocumentFile类。