Android按名称查询DocumentFile时ContentResolver忽略selection参数问题
问题原因分析
这是Android存储访问框架(SAF)的典型特性限制:绝大多数DocumentsProvider实现不会处理query方法传入的selection、selectionArgs、sortOrder参数,包括系统自带的外部存储DocumentsProvider、第三方文件应用实现的Provider,都会直接忽略你传入的筛选条件,固定返回当前目录下的所有子文档列表。
SAF官方规范本身没有强制要求Provider支持自定义查询条件,所以依赖selection做服务端筛选的写法本身就不兼容绝大多数场景。
正确实现方案
你需要查询当前目录下的所有文档,然后在本地遍历匹配文件名:
final ContentResolver resolver = mContext.getContentResolver(); final Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(mUri, DocumentsContract.getDocumentId(mUri)); Cursor c = null; try { // 不要传selection参数,直接查询所有子文档 c = resolver.query(childrenUri, new String[] { DocumentsContract.Document.COLUMN_DOCUMENT_ID, DocumentsContract.Document.COLUMN_DISPLAY_NAME }, null, null, null); while (c.moveToNext()) { // 本地遍历匹配文件名 String curName = c.getString(1); if (displayName.equals(curName)) { final String documentId = c.getString(0); final DocumentFile result = new TreeDocumentFile(this, mContext, DocumentsContract.buildDocumentUriUsingTree(mUri, documentId)); return result; } } } catch (Exception e) { Log.w(TAG, "Failed query: " + e); } finally { closeQuietly(c); } return null;
注意事项
- 匹配文件名时注意区分大小写,不同文件系统的大小写敏感规则不同,如果需要兼容全场景可以统一转大写/小写后再匹配
COLUMN_DISPLAY_NAME返回的是包含后缀的完整文件名,匹配时需要和输入的displayName完全一致
内容的提问来源于stack exchange,提问作者user1026605
相关产品推荐
相关产品推荐

