Android:从CONTENT URI获取同目录文件及访问ownCloud目录
解决两个ownCloud文件访问问题:同目录文件获取与目录选择
一、从单个文件Content URI获取同目录文件列表
第三方文档Provider(如ownCloud)的URI结构和MediaStore差异较大,不能直接用常规MediaStore字段查询目录文件,需通过DocumentsContract接口处理:
步骤1:解析当前文件的父目录ID/URI
ownCloud的文档ID通常格式为父目录ID/文件ID(比如示例URIcontent://org.owncloud.documents/document/79对应的文档ID可能是78/79),可通过以下方式获取父目录信息:
import android.provider.DocumentsContract // 1. 获取当前文件的文档ID val docId = DocumentsContract.getDocumentId(uri) // 2. 拆分文档ID得到父目录ID(根据ownCloud格式调整) val parentDocId = docId.split("/").firstOrNull() ?: return // 3. 构造父目录的Content URI val parentDirUri = DocumentsContract.buildDocumentUri("org.owncloud.documents", parentDocId)
如果拆分方式不适用,也可以直接查询当前文件的父目录ID字段:
val projection = arrayOf(DocumentsContract.Document.COLUMN_PARENT_DOCUMENT_ID) context.contentResolver.query(uri, projection, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { val parentDocId = cursor.getString(cursor.getColumnIndexOrThrow( DocumentsContract.Document.COLUMN_PARENT_DOCUMENT_ID )) val parentDirUri = DocumentsContract.buildDocumentUri("org.owncloud.documents", parentDocId) // 后续查询父目录文件 } }
步骤2:查询父目录下的所有文件
用构造好的父目录URI查询子文件,使用DocumentsContract标准列(避免用MediaStore的DATA字段,第三方Provider可能不支持):
val fileProjection = arrayOf( DocumentsContract.Document.COLUMN_DISPLAY_NAME, DocumentsContract.Document.COLUMN_DOCUMENT_ID, DocumentsContract.Document.COLUMN_MIME_TYPE ) context.contentResolver.query(parentDirUri, fileProjection, null, null, null)?.use { cursor -> while (cursor.moveToNext()) { val fileName = cursor.getString(cursor.getColumnIndexOrThrow( DocumentsContract.Document.COLUMN_DISPLAY_NAME )) val fileDocId = cursor.getString(cursor.getColumnIndexOrThrow( DocumentsContract.Document.COLUMN_DOCUMENT_ID )) // 构造单个文件的Content URI val fileUri = DocumentsContract.buildDocumentUri("org.owncloud.documents", fileDocId) // 处理文件信息(如存入列表) } }
二、解决ACTION_OPEN_DOCUMENT_TREE无法访问ownCloud的问题
ACTION_OPEN_DOCUMENT_TREE无法识别ownCloud,通常是因为ownCloud的DocumentsProvider未适配该Intent,可尝试以下方案:
- 更新ownCloud应用:部分旧版本ownCloud未实现目录选择支持,更新到最新版本后可能解决。
- 替代方案:批量选择文件:使用
ACTION_GET_CONTENT并开启多选,让用户手动选择同目录文件:val intent = Intent(Intent.ACTION_GET_CONTENT).apply { type = "*/*" putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) addCategory(Intent.CATEGORY_OPENABLE) } startActivityForResult(intent, REQUEST_CODE_PICK_FILES) - 申请父目录持久权限:如果已经通过单个文件URI获得访问权限,可对父目录申请持久化权限,后续直接通过代码访问目录:
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION try { context.contentResolver.takePersistableUriPermission(parentDirUri, flags) } catch (e: SecurityException) { // 处理权限申请失败 } - 查看ownCloud自定义Intent:部分应用会提供自定义Intent用于目录选择,可查阅ownCloud官方开发者文档寻找对应接口。
内容的提问来源于stack exchange,提问作者hannes ach
相关产品推荐
相关产品推荐

