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

Espresso测试重启后出现No persistable permission grants found for UID错误的解决方法

Espresso测试重启后出现持久化权限错误

应用权限请求与持久化实现

应用通过以下代码请求文件夹访问权限:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.provider.extra.SHOW_ADVANCED", true);

mStartChooseFolderForResult.launch(intent);

在onActivityResult中处理权限持久化:

public void onActivityResult(ActivityResult result)
{
    if (result.getResultCode() == Activity.RESULT_OK)
    {
        Intent intent = result.getData();
        Uri uri = intent.getData();
        ContentResolver cr = getActivity().getContentResolver();
        int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
                  | Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
        cr.takePersistableUriPermission(uri, flags);
        ...
    }
}

测试代码

Espresso测试中模拟文件夹选择结果:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.setData(Uri.parse(DEFAULT_FOLDER_STRING + "%2F" + testFolder));
Instrumentation.ActivityResult result = new 
    Instrumentation.ActivityResult(Activity.RESULT_OK, intent);
intending(hasAction(Intent.ACTION_OPEN_DOCUMENT_TREE)).respondWith(result);
    
onView(withText("select")).perform(click());

问题现象

  • 手动运行应用时,持久化权限正常生效,重启设备后权限仍保留。
  • 设备重启后直接运行Espresso测试,抛出错误:No persistable permission grants found for UID...
  • 若先手动打开应用选择测试指定文件夹,再运行测试则无异常。

解决方法

问题根源在于测试中仅模拟了Uri返回,但未触发系统层面的持久化权限授予流程——手动操作时系统会自动为选中的Uri临时授予权限,再通过takePersistableUriPermission转为持久化权限;而Espresso模拟的Intent结果没有附带权限标记,导致takePersistableUriPermission无法生成有效持久化权限。

可以通过以下两种方式解决:

方式1:在测试中手动添加权限标记

修改模拟返回的Intent,添加临时权限标记,确保takePersistableUriPermission能正常持久化:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
Uri folderUri = Uri.parse(DEFAULT_FOLDER_STRING + "%2F" + testFolder);
intent.setData(folderUri);
// 为Intent添加临时权限标记
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, intent);
intending(hasAction(Intent.ACTION_OPEN_DOCUMENT_TREE)).respondWith(result);

方式2:在测试中直接授予持久化权限

如果模拟Intent仍无法解决,可在测试初始化阶段,直接通过Instrumentation调用ContentResolver授予持久化权限:

@Before
public void setUp() {
    // 初始化测试环境
    Uri folderUri = Uri.parse(DEFAULT_FOLDER_STRING + "%2F" + testFolder);
    ContentResolver cr = InstrumentationRegistry.getInstrumentation().getTargetContext().getContentResolver();
    int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
    
    // 先尝试移除已有权限(避免重复授予报错)
    try {
        cr.releasePersistableUriPermission(folderUri, flags);
    } catch (Exception e) {
        // 无权限时忽略异常
    }
    // 授予持久化权限
    cr.takePersistableUriPermission(folderUri, flags);
}

额外注意事项

  • 确保测试设备的API版本与应用目标版本一致,不同版本的Uri权限处理逻辑可能有差异。
  • 若使用Android 11+,需注意MANAGE_EXTERNAL_STORAGE权限与SAF权限的兼容性,但此问题中核心是SAF的持久化权限,因此无需额外申请该权限。

内容的提问来源于stack exchange,提问作者Laurent D.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:40:44