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

Android应用已授予权限仍报Eaccess Permission Denied问题求助

解决Android中已授予存储权限但仍提示Permission Denied的问题

嘿,看了你的代码和问题描述,虽然你已经添加了存储权限并做了权限检查,但还是遇到了Permission Denied,这大概率是Android版本的存储机制变化导致的,我来给你拆解几个核心原因和对应的解决方案:


1. 先确认:你是否漏了动态权限申请流程

虽然你在代码里做了权限状态检查,但如果用户还没有授予权限,你的代码并没有触发权限申请的弹窗流程。就算你说已经手动授予了权限,也建议补全这个流程,避免其他场景下的权限遗漏:

public class MainActivity extends AppCompatActivity {
    public static final String TAG = "DEBUG_";
    private static final int REQUEST_STORAGE_PERMISSION = 100;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView = findViewById(R.id.image_view);

        // 检查权限状态,未授予则发起申请
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, 
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 
                    REQUEST_STORAGE_PERMISSION);
        } else {
            loadImage(imageView);
        }
    }

    // 处理权限申请结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_STORAGE_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                ImageView imageView = findViewById(R.id.image_view);
                loadImage(imageView);
            } else {
                Toast.makeText(this, "需要存储权限才能加载图片", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void loadImage(ImageView imageView) {
        String imagePath = "/storage/emulated/0/DCIM/Camera/IMG_20200118_175558.jpg";
        File imageFile = new File(imagePath);
        // 先检查文件是否存在,避免混淆权限问题
        if (imageFile.exists()) {
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            imageView.setImageBitmap(bitmap);
        } else {
            Log.d(TAG, "图片文件不存在,请检查路径");
        }
    }
}

2. Android 10+的分区存储限制是核心问题

从Android 10(API 29)开始,系统默认启用了分区存储机制——即使你拥有READ_EXTERNAL_STORAGE权限,直接访问文件的绝对路径也会被拒绝。针对这个问题有两种方案:

方案A:临时兼容旧存储模式(仅适用于API 29)

在Manifest的application标签中添加android:requestLegacyExternalStorage="true",可以暂时绕过分区存储限制:

<application 
    android:allowBackup="true" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:roundIcon="@mipmap/ic_launcher_round" 
    android:supportsRtl="true" 
    android:theme="@style/AppTheme"
    android:requestLegacyExternalStorage="true"> <!-- 新增这个属性 -->
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

注意:这个属性在Android 11(API 30)及以上版本会被忽略,无法生效。

方案B:适配分区存储(推荐,长期有效)

使用MediaStore API获取图片的Uri,再通过ContentResolver打开输入流解码Bitmap,这是Android官方推荐的合规方式:

private void loadImageWithMediaStore(ImageView imageView) {
    String imagePath = "/storage/emulated/0/DCIM/Camera/IMG_20200118_175558.jpg";
    // 通过MediaStore查询获取图片Uri
    Uri uri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
    String[] projection = {MediaStore.Images.Media._ID};
    String selection = MediaStore.Images.Media.DATA + "=?";
    String[] selectionArgs = {imagePath};

    Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, null);
    if (cursor != null && cursor.moveToFirst()) {
        long imageId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
        Uri imageUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageId);
        
        try (InputStream inputStream = getContentResolver().openInputStream(imageUri)) {
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            imageView.setImageBitmap(bitmap);
        } catch (IOException e) {
            Log.e(TAG, "加载图片失败", e);
        }
        cursor.close();
    } else {
        Log.d(TAG, "未找到对应图片,请检查路径");
    }
}

3. 额外排查点:确认文件路径正确性

有时候权限报错可能是因为文件本身不存在,建议在解码前先通过File.exists()检查文件状态,避免把文件不存在的问题误判为权限问题。

内容的提问来源于stack exchange,提问作者Francesco Greco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:54:06