Android高版本的Uri及其使用注意问题

86 篇文章 36 订阅

一、前言

Uri又被成为统一资源定位符。顾名思义,是用来定位资源的。在Android中主要是用来定位本地资源的。在Android10.0以前由于可以直接使用File进行文件读写,所以Uri的使用范围没那么广。只有使用存放在rawasset或者其它资源文件时候,以及使用ContentProvider这些方式的时候才进行使用Uri。相对于整个项目来说,频率较低。但是

由于Android10.0开始强制逐步强制使用SAF的方式进行文档读写。因此Uri开始很频繁的被开发者进行使用。本篇文章对一些不同场景下Uri的生成和使用进行一个整理和总结。

二、Document

Android中的文档体系中,Android把所有文档都用一个id进行标识。所以理论上知道id可以获取对应的位置,可以通过以下代码进行获取

ContentUris.withAppendedId(uri,id) 

下面是一个MediaStore示例:

  val mediaInfoList = arrayListOf<MediaInfo>()
        val uri = MediaStore.Files.getContentUri("external")
        val selection =
            "(" + MediaStore.Files.FileColumns.DATA + " LIKE '%ym_empty%'" + ")"
        val cursor: Cursor? = contentResolver.query(uri, null, selection, null, null)
        try {
            cursor!!.moveToFirst()
            while (!cursor.isAfterLast) {
                val id = cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID))
                val contentUri = ContentUris.withAppendedId(
                    uri,
                    id
                ) 
                cursor.moveToNext()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            cursor?.close()
        }

这个链接的样子如下:

content://media/external/images/media/272

可以将该Uri转换为DocumentFile.

  val documentFile =
                    DocumentFile.fromSingleUri(RockeyApp.getInstance()!!, contentUri)

还有一种将File转换为DocumentFile的方式,如下:

比如文档的路径为/storage/emulated/0/Download/1-1604402012.png

val documentFile = DocumentFile.fromFile(file)

通过以上方式转换完的路径为
file:///storage/emulated/0/Download/1-1604402012.png

可以看到这个路径和之前的路径是不太一样的,但是依然可以正常使用。

另外通过这种方式转换的Uri可以再次转换为File,其余方式则不可以

val documentFile = DocumentFile.fromFile(file)
val newFile = documentFile.uri.toFile()

需要注意的是,在Android中有些文件其实不存在了,但是File.exists()依然会判断存在,这里使用DocumentFile.exists()函数才会返回正确结果

使用SAF获取的路径如下:

content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fmedia%2Fcom.whatsapp

可以看到这种路径和上面的也不太一样。

三、文件删除

上面已经知道可以通过File、id、SAF等方式转换成为DocumentFile。但是在执行删除操作时候却并不能都按照DocumentFile进行文件删除。还是需要使用各自的方式进行删除。只有使用SAF方式获取的文件可以使用DocumentFile进行删除。

1、File

val file = File(path)
file.delete()

2、MediaStore

val file = File(path)
val filePath = file.path
                    val res: Int = contentResolver.delete(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        MediaStore.Images.Media.DATA + "= \"" + filePath + "\"",
                        null
                    )

3、DocumentFile

val dirDocument =
   DocumentFile.fromSingleUri(RockeyApp.getInstance()!!, Uri.parse(fileStr))
   val isDel = dirDocument?.delete()

四、参考链接

  1. Uri

  2. Android中的Uri详解_JMW1407的博客-CSDN博客_android uri

  3. Is it possible to get a regular File from DocumentFile?

  4. DocumentFile  |  Android Developers

  5. DocumentsContract  |  Android Developers

  6. Storage Access Framework_光英的记忆博客-CSDN博客

  7. Android content 类型的 Uri 转换成绝对路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值