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
相关产品推荐
相关产品推荐

