一、前言
Uri又被成为统一资源定位符。顾名思义,是用来定位资源的。在Android中主要是用来定位本地资源的。在Android10.0以前由于可以直接使用File进行文件读写,所以Uri的使用范围没那么广。只有使用存放在raw、asset或者其它资源文件时候,以及使用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()