kotlin:如何在Android中读取Uri?
这件事我已经坚持了将近一个星期了。我找到了几乎所有的答案/教程,但还没有找到运气 我有一个使用相机的应用程序。在用户拍摄了一张照片,并选择相机中的check/OK按钮后,相机会返回存储图像的Uri。它以:kotlin:如何在Android中读取Uri?,android,kotlin,Android,Kotlin,这件事我已经坚持了将近一个星期了。我找到了几乎所有的答案/教程,但还没有找到运气 我有一个使用相机的应用程序。在用户拍摄了一张照片,并选择相机中的check/OK按钮后,相机会返回存储图像的Uri。它以:content://media/external/images/media/122(这是手机中的实际图片),如果我询问Uri.path,我将在本例中得到:/external/images/media/123 现在,有了Uri对象,我可以将它分配给一个imageView,如imageView.se
content://media/external/images/media/122
(这是手机中的实际图片),如果我询问Uri.path,我将在本例中得到:/external/images/media/123
现在,有了Uri对象,我可以将它分配给一个imageView,如imageView.setImageURI()
,它就可以工作了,所以我非常确信这些图像存储在某个地方
现在,我的应用程序应该做的下一件事是拍摄所有拍摄的照片,并将它们发送到API
我的问题是,当我尝试用任何方法读取Uri时,它都会给我一个FileNotFound异常
,无论我使用的是Uri还是路径
所以我真的不知道该怎么办。我错过了什么?是否必须将映像显式保存在工作目录中?如果是,是如何做到的?如果没有,如何获取包括文件名在内的完整路径名?当我在电话里看DCIM导演时,我没有找到照片
提前谢谢
编辑
获取pic的代码:
btnTomarFoto.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(android.Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_DENIED || ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_DENIED
) {
// El permiso no fue concedido
val permission = arrayOf(android.Manifest.permission.CAMERA,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
requestPermissions(permission, PERMISSION_CODE)
} else {
// El permiso ya estaba concedido
openCamera()
}
} else {
// El SO es menor que Marshmallow
}
}
}
打开相机的代码:
private fun openCamera() {
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "New Picture")
values.put(MediaStore.Images.Media.DESCRIPTION, "From the camera")
image_uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
startActivityForResult(cameraIntent, IMAGE_CAPTURE_CODE)
}
将Uri存储到数据库中的代码:
private fun guardarFoto() {
var foto = FotografiaModel(actividad_id!!, image_uri.toString(), txtObservacion.text.toString())
Log.w(tag, "URI: $image_uri PATH: " + image_uri!!.path + " Encoded Path: " + image_uri!!.encodedPath)
fotografiaDBHelper.insertFoto(foto)
visitaDBHelper.actualizaEstado(actividad_id!!, "INICIADO")
}
代码还可以做更多的事情,但这是最主要的。要在Imageview中显示收到的Uri,我使用:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
imageView.setImageURI(image_uri)
Log.v(tag, "Image URI: $image_uri")
}
}
我的问题是,当我尝试用任何方法读取Uri时,它都会给我一个FileNotFound异常,无论我使用的是Uri还是路径
这是因为它不是一个文件。它是一个Uri
例如,https://stackoverflow.com/questions/56839478/kotlin-how-to-read-a-uri-in-android
是一个Uri
。您的代码假设路径/questions/56839478/kotlin-how-to-read-a-uri-in-android
是uri
中唯一重要的东西。根据你的论点,地球上的每一台计算机(加上轨道上的计算机)都有一个文件位于/questions/56839478/kotlin-how-to-read-a-uri-in-android
。这不是Uri
的工作方式。您需要使用整个Uri
来确定如何使用它。在这种情况下,https
作为一种方案意味着您使用https作为协议与指定的服务器(stackoverflow.com
)对话以检索内容
类似地,来自insert()
的Uri
中的content
方案指示您使用ContentResolver
来处理它。特别是,您可以使用openInputStream()
在Uri
标识的内容上获取InputStream
,就像您可以使用HttpUrlConnection
或OkHttp在https
Uri
上获取InputStream
一样
特别是,由于您将数据存储委托给了其他应用程序(MediaStore),因此存储映像的位置由其他人决定,并且映像不一定位于文件系统中您可以访问的位置。在Android Q和更高版本上尤其如此,在Android Q和更高版本中,您可以通过文件系统API限制对设备上任意位置的访问
现在,我的应用程序应该做的下一件事是拍摄所有拍摄的照片,并将它们发送到API
我猜“将它们发送到API”意味着“将它们上传到服务器”(而不是“调用设备上库公开的API”或“调用Android SDK中的方法”)。在这种情况下,您有一些与该服务器对话的代码。它可能是通用代码(如OkHttp、改型)或特定于API的代码(如Facebook SDK)
无论如何,您需要查看该代码对图像内容的支持:
- 如果它支持
,请尝试使用Uri
Uri
- 如果它支持
(或某种类型的InputStream
),请在Reader
ContentResolver上使用
openInputStream()
- 如果它支持
或FileDescriptor
,请在AssetFileDescriptor
ContentResolver上使用
openFileDescriptor()
- 如果它只支持
,而不是使用File
获取contentResolver.insert()
以发送到相机应用程序,请使用Uri
,以便将图像保存在您控制的文件中(例如,在FileProvider
中)getCacheDir()
- 等等
表单通过邮件传递的文件。我正在使用截击,我发现它非常容易使用,而且对于我正在尝试做的事情来说已经足够了。@luisfer:我没有使用截击来满足这种请求,所以我无法提供如何使用它的详细信息。最有可能的情况是,您将以某种形式使用ContentResolver
和openInputStream()
。