You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:07:23