Android 13照片/视频选择器 - URI的文件名是垃圾。

7

当使用 Android 13 中引入的选择器时,通过 ActivityResultContracts.PickVisualMedia 返回一个 Uri(表示所选媒体项):

content://media/picker/0/com.android.providers.media.photopicker/media/1000000198

如果我使用内容解析器并查询游标,我会得到类似以下的结果:
duration = 38003
orientation = 0
height = 2336
_display_name = 1000000198.mp4
datetaken = 1681826421000
mime_type = video/mp4
_data = /sdcard/.transforms/synthetic/picker/0/com.android.providers.media.photopicker/media/1000000198.mp4
_size = 9920806
width = 1072

通常用于文件名的列是OpenableColumns.DISPLAY_NAME(_display_name)。但是,正如您所看到的,这里的值只是一些垃圾数字文件名,而不是实际选择的文件名。这不是所选视频的实际文件名

有没有办法使用Android 13照片/视频选择器并获取用户选择的文件的实际文件名,而不是这个垃圾数字文件名?


你应该发布你的代码。然后告诉获得的值。 - blackapps
此外,它不是一个垃圾编号名称,因为它等于该内容方案的最后一个路径段,并且它将成为提供者数据库中的索引。 - blackapps
获取显示名称的另一种方法是DocumentFile.fromSingleUri(context, uri).getName(),但对于这个媒体选择器方案也不起作用。我认为@CommonsWare来解救了。 - blackapps
即使使用MediaStore.Images.Media.TITLE而不是DISPLAY_NAME列,也没有任何结果。 - blackapps
有完全相同的问题。关于这个问题有任何更新吗? - grandbora
显示剩余4条评论
2个回答

1
从我的个人研究来看,我认为无法从照片选择器中获取文件/显示名称。
这是一个未解决的问题(截至目前为止),Google还没有回应这个请求。
目前我能看到的唯一选择是要么接受我们无法获取文件名并希望将来修复,要么实现自己的文件/照片选择器(当然,这需要额外的权限,因为它不是系统应用程序)。

0
据我所了解,照片选择器返回的URI是内容提供者URI。内容提供者应该提供满足您使用情况的API,而无需实际文件路径。请随意阅读文档:https://developer.android.com/guide/topics/providers/content-providers 目前我想到的解决方法是使用_data列中的值作为路径。在我的情况下,我需要访问帧。我能够将此路径设置为MediaMetadataRetriever实例的数据源。以下是我的示例代码(免责声明:我绝不是Android专家。此代码可能不适用于生产环境)。
    fun processUri(selectedImageUri: Uri) {
        val cursor: Cursor? = contentResolver.query(
            selectedImageUri, null, null, null, null, null
        )

        if (cursor == null) {
            //...
        }
        if (cursor.count == 0) {
            //...
        }
        if (!cursor.moveToFirst()) {
            //...
        }

        val dataColIndex = cursor.getColumnIndex("_data")
        val dataPath: String = cursor.getString(dataColIndex)
        val frame = getFrame(dataPath, 0)

        state.update { _ ->
            // use frame
        }
    }

    private fun getFrame(dataPath: String, timeUs: Long): Bitmap? {
        val retriever = MediaMetadataRetriever()
        try {
            retriever.setDataSource(dataPath)
            return retriever.getFrameAtTime(timeUs, MediaMetadataRetriever.OPTION_CLOSEST)
        } catch (ex: IllegalArgumentException) {
            //...
        } catch (ex: RuntimeException) {
            //...
        } finally {
            try {
                retriever.release()
            } catch (ex: RuntimeException) {
                //...
            }
        }
    }

PS.使用 _data 列似乎是内置到 API 中的约定。请查看 openFileHelper 方法。


你能解释一下如何从帧中获取文件名吗?因为这是问题... - Pierre Michel
我能给出的最好答案是查看我提供的链接中记录的内容提供者API。我的使用情况不需要实际的文件名,我还没有进行调查。希望这至少能给你一个方向。 - grandbora
这也给出了相同的名称。并非实际文件名。 - Ahsan Ullah Rasel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接