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

Android应用读取媒体文件崩溃:SecurityException权限问题排查

问题解决:MediaDocumentsProvider URI 权限拒绝导致崩溃

问题描述

已申请存储权限且日志显示权限已授予,但在RecyclerView中展示图片时,下拉返回或跳转至使用该图片的其他Activity时崩溃,报错信息:

java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com.android.providers.media.documents/document/image%3A1000067180 from pid=29739, uid=10242 requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

核心展示代码:

// onBindViewHolder: Binds data to the views in each ViewHolder
@Override
public void onBindViewHolder(@NonNull PostsListAdapter.PostViewHolder holder, int position) {
    if (posts != null) {
        final Post current = posts.get(position);
        holder.tvAuthor.setText(current.getAuthor());
        holder.tvcontent.setText(current.getContent());
        holder.ivPic.setImageURI(current.getPic());
        holder.ivProfile.setImageURI(current.getProfile());
        holder.tvLikes.setText(String.valueOf(current.getLikes()));
     }
}

问题根源

普通的READ_EXTERNAL_STORAGE权限无法访问MediaDocumentsProvider提供的URI——这类URI是系统文件选择器生成的,属于文档级别的独立访问权限,和全局存储权限是两个概念。即使申请了存储权限,应用切换页面、重启后,临时的URI访问权限会自动失效,触发读取时的权限拒绝。

解决方案

1. 改用ACTION_OPEN_DOCUMENT获取图片URI

放弃直接通过文件路径或普通权限访问的方式,使用系统提供的ACTION_OPEN_DOCUMENT(推荐)选择图片,这类API会自动申请临时访问权限:

// AndroidX推荐的ActivityResult方式
registerForActivityResult(new ActivityResultContracts.OpenDocument(), uri -> {
    if (uri != null) {
        // 持久化URI权限,避免页面切换或重启后失效
        int takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
        getContentResolver().takePersistableUriPermission(uri, takeFlags);
        // 将持久化后的URI保存到Post对象
        Post newPost = new Post(...);
        newPost.setPic(uri);
        posts.add(newPost);
        adapter.notifyDataSetChanged();
    }
}).launch(new String[]{"image/*"});

2. 强制持久化URI权限

获取URI后必须调用takePersistableUriPermission,让系统保留该URI的长期访问权限,这是解决页面切换后权限失效的核心步骤。

3. 验证URI权限有效性(可选)

如果需要提前判断URI是否还能访问,可添加权限检查逻辑:

public boolean hasUriPermission(Context context, Uri uri) {
    int permission = context.getContentResolver().checkUriPermission(uri,
            android.os.Process.myPid(), android.os.Process.myUid(),
            Intent.FLAG_GRANT_READ_URI_PERMISSION);
    return permission == PackageManager.PERMISSION_GRANTED;
}

若权限失效,需重新引导用户选择图片。

内容的提问来源于stack exchange,提问作者yael dahari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 13:13:32