如何解决将媒体文件路径或 URI 保存到 SQLite 并获取它,最佳实践
我的目标是:
- 将媒体文件保存到外部存储(在我的例子中是照片)。
- 获取已保存数据的文件路径或 URI。
- 将其保存到 SQLite(文件路径或内容 URI 或其他)。
- 能够在未来的任何时候获得此内容的正确 URI。
它与其他非常流行的应用程序所做的非常相似 - 他们在“图片”文件夹中创建他们的目录,并将照片存储在那里,并在他们的应用程序中使用它们,同时还可以使用图库/文件浏览器等查看它们。
>据我所知,保存媒体内容(图像,f.e.)的推荐方法是使用 MediaStore
API,因此我获得了内容 URI,以后可以使用。
但是后来我读到这些内容 URI 在重新扫描媒体后可能会更改,因此它看起来不可靠。 (例如如果使用了 SD 卡,然后将其取出并重新插入)
同时,不推荐使用绝对文件路径,并且倾向于弃用使用绝对文件路径来处理外部存储的 API。所以看起来也不靠谱。
我只能想象以下解决方案:
- 保存时使用唯一的自动生成的文件名(如 UUID)。
- 当我需要获取内容 URI 时(例如想要在
ImageView
中渲染照片)- 我可以使用ContentResolver
并使用文件名过滤器搜索内容 URI。
这种方法的问题是我有很多照片(图库),使用 ContentResolver
查询它会显着影响性能。
我觉得我把事情复杂化了,错过了一些东西。
解决方法
你确实把事情复杂化了。 将文件存储到文件系统中所需的文件夹中(最好将文件夹命名为您的应用程序名称)
存储此路径或 URI 路径 - 无论您喜欢什么。 (不要在您的应用中对传递进行硬编码 - 设备供应商在他们的设备中可能有不同的基本路径)
只要文件夹的名称相同并且其中的文件名称相同(与您的数据库中的名称相同) - 即使取出 SD 卡然后重新放入,您也可以访问它们。
重新索引后可能会出现并发症 - 但在我作为 Android 开发人员工作的八年中,我只遇到过一次,因此您可以轻松忽略这些东西。
如果您想对存储的内容有更多的控制权并希望限制对其的访问 - 将数据存储到应用程序的内部存储中 - 这样您就可以 100% 确定数据在哪里,它不在被篡改。
从 Android 10 开始,您有范围存储 - 它就像内部存储,但它甚至可能位于外部 sdcard 上。
Here 是可能的存储位置的简要概述。
不要想太多 - 它是手机的默认用例,它的工作原理与您预期的一样 - 非常好且非常稳定。
,我建议您使用 Intent.ACTION_OPEN_DOCUMENT
来满足您的需求。
1.创建照片挑选Intent
:
val REQUEST_CODE_PICK_PHOTO = 1
fun pickAndSavePhoto(requestCode: Int) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.type = "image/*"
startActivityForResult(intent,requestCode)
}
2.处理结果:
override fun onActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
super.onActivityResult(requestCode,resultCode,data)
if (requestCode == REQUEST_CODE_PICK_PHOTO && resultCode == RESULT_OK) {
val imageUri = data!!.data!!
//save this uri to your database as String -> imageUri.toString()
}
}
3.取回图像并在 ImageView
上显示:
fun getBitmapFromUri(context: Context,imageUri: Uri): Bitmap? { //uri is just an address,image may be deleted any time,if so returns null
val bitmap: Bitmap
return try {
val inputStream = context.contentResolver.openInputStream(imageUri)
inputStream.use {
bitmap = BitmapFactory.decodeStream(it)
}
bitmap
} catch (e: Exception) {
Log.e("getBitmapFromUri()","Image not found.")
null
}
}
val bitmap = getBitmapFromUri(context,imageUri) //get uri String from database and convert it to uri -> uriString.toUri()
if (bitmap != null) {
imageView.setImageBitmap(bitmap)
}
-
只有
ACTION_OPEN_DOCUMENT
可以永久访问文件 uri: Android Retrieve Image by Intent Uri Failed: "has no access to content..."
首先需要在manifest和Runtime Permission中申请外部存储权限。
在此目录中创建用于保存图像的目录之后。
您还必须在 XML 和代码端添加文件提供程序,因为它是必需的。
现在是时候检查我的代码以将图像保存在文件夹中以及图库中的这些图像并从文件路径中获取路径。
-
- 将 URI 转换为位图
-
- 获取位图保存图像功能
private String save(Bitmap bitmap) {
File save_path = null; if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { try { File sdCard = Environment.getExternalStorageDirectory(); File dir = new File(sdCard.getAbsolutePath() + "/SaveDirectory"); dir.mkdirs(); File file = new File(dir,"DirName_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()) + ".png"); save_path = file; ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG,100,baos); FileOutputStream f = null; f = new FileOutputStream(file); MediaScannerConnection.scanFile(context,new String[]{file.getAbsolutePath()},null,null); if (f != null) { f.write(baos.toByteArray()); f.flush(); f.close(); } } catch (Exception e) { // TODO: handle exception } Share(save_path); // call your Function Store into database Log.e("PathOFExec----","save: " + save_path); }
-
- 如果您愿意,可以将存储图像位置添加到您的数据库中
private void Share(File savePath) {
if (savePath != null) { Uri uri = FileProvider.getUriForFile(context,context.getApplicationContext().getPackageName() + ".provider",savePath); Intent share = new Intent(Intent.ACTION_SEND); share.setType("image/*"); share.putExtra(Intent.EXTRA_TEXT,"TextDetail"); share.putExtra(Intent.EXTRA_STREAM,uri); context.startActivity(Intent.createChooser(share,"Share Image!")); //after getting URI you can store the image into SQLite databse for get uri }
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。