Android跨应用传递Uri后接收应用无法访问文档树问题
问题原因
- 跨应用传递Uri时,原应用获取的文档树访问权限未授予接收应用,导致接收应用无权限读取对应内容
- 接收应用错误使用子文档Uri创建
DocumentFile,而非直接使用传入的树Uri
解决步骤
1. 原应用:传递Uri时授予接收应用访问权限
启动接收应用的Intent中需明确授予Uri读取权限,两种实现方式可选:
方式一:通过Intent标记授予权限
修改原应用onActivityResult中启动接收应用的代码:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case FILE_SELECT_CODE: if (resultCode == RESULT_OK) { Uri uri = data.getData(); Intent intent = new Intent(); intent.setComponent(new ComponentName("com.tiferet.update", "com.tiferet.update.MainActivity")); intent.setData(uri); // 添加权限标记,授予接收应用读取Uri的权限 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 若需持久化权限(重启后仍有效),可添加以下标记,后续需配合takePersistableUriPermission处理 // intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); startActivity(intent); } break; } super.onActivityResult(requestCode, resultCode, data); }
方式二:通过ContentResolver直接授予权限(更稳妥)
若方式一无效,可直接通过ContentResolver将Uri权限授予接收应用包名:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case FILE_SELECT_CODE: if (resultCode == RESULT_OK) { Uri uri = data.getData(); Intent intent = new Intent(); intent.setComponent(new ComponentName("com.tiferet.update", "com.tiferet.update.MainActivity")); intent.setData(uri); // 直接授予接收应用包名读取该Uri的权限 getContentResolver().grantUriPermission("com.tiferet.update", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent); } break; } super.onActivityResult(requestCode, resultCode, data); }
2. 接收应用:修正DocumentFile创建方式
直接使用传入的树Uri创建DocumentFile,修改ProcessMe方法:
public void ProcessMe(Uri uri) { // 直接用传入的树Uri创建DocumentFile DocumentFile tree = DocumentFile.fromTreeUri(this, uri); DocumentFile[] documents = tree.listFiles(); Toast.makeText(this, String.valueOf(documents != null ? documents.length : 0), Toast.LENGTH_SHORT).show(); if (documents != null) { for (DocumentFile doc : documents) { Log.w("itapiIkosher", doc.getName()); } } }
额外说明
- 若需接收应用重启后仍能访问该Uri,原应用需添加
FLAG_GRANT_PERSISTABLE_URI_PERMISSION标记,接收应用拿到Uri后需调用getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)持久化权限 - 确保接收应用Manifest中无权限限制类声明,避免权限冲突
内容的提问来源于stack exchange,提问作者itapi
相关产品推荐
相关产品推荐

