Android 13模拟器中READ_EXTERNAL_STORAGE权限请求不显示问题
权限请求在Android 13(API 33)模拟器上无响应的解决方案
我通过Map<Integer, Runnable>实现了Activity权限请求的结果处理器:请求权限时生成随机请求码,将请求码与对应的处理逻辑绑定,权限回调时执行对应逻辑。该实现在Android 12(API 31)真机上运行正常,但在Android 13(API 33)模拟器上出现异常:权限请求无弹窗,权限始终未授予,且Manifest中声明的权限未在应用信息中显示。
一、权限处理实现代码
private final HashMap<Integer, Runnable> onPermission = new HashMap<>(); // 从其他类调用此方法请求权限并注册处理器 public void requestPermission(Runnable onGranted, String...permissions) { int code = Permissions.permissionRequestCode(); onPermission.put(code, onGranted); requestPermissions(permissions, code); } // 重写此方法检查是否有对应请求码的处理器 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { Runnable handler = onPermission.get(requestCode); if (handler != null && isGranted(grantResults)) { handler.run(); onPermission.remove(requestCode); } super.onRequestPermissionsResult(requestCode, permissions, grantResults); } // 检查所有请求权限是否被授予的工具方法 private boolean isGranted(int[] results) { for (int i : results) { if (i != PackageManager.PERMISSION_GRANTED) { return false; } } return true; }
二、使用示例
private void readImages() { if (ContextCompat.checkSelfPermission(owner, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { loadImages(); } else { owner.requestPermission(this::loadImages, Manifest.permission.READ_EXTERNAL_STORAGE); } }
三、Manifest配置
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="Mesa" android:roundIcon="@mipmap/ic_launcher" android:supportsRtl="true" android:theme="@style/Theme.Mesa.NoActionBar" android:usesCleartextTraffic="true"> <activity android:name=".app.Mesa" android:configChanges="uiMode|screenSize|colorMode" android:exported="true" android:theme="@style/Theme.Mesa.NoActionBar" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
四、build.gradle配置
android { compileSdk 33 defaultConfig { applicationId "org.luke.mesa" minSdk 24 targetSdk 33 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" proguardFiles 'proguard-rules.pro' } buildTypes { release { minifyEnabled true } debug { minifyEnabled false } } compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 allprojects { tasks.withType(JavaCompile){ options.compilerArgs <<"-Xlint:deprecation" } } } buildFeatures { viewBinding true dataBinding true } packagingOptions { resources { merges += ['META-INF/DEPENDENCIES'] } } namespace 'org.luke.mesa' dependenciesInfo { includeInApk true includeInBundle true } buildToolsVersion '33.0.0' }
解决方案
1. 适配Android 13存储权限变更
Android 13(API 33)彻底重构了存储权限体系,READ_EXTERNAL_STORAGE被标记为废弃,系统不再为该权限触发弹窗请求,直接返回拒绝状态,且该权限不会在应用信息中展示。需根据媒体类型使用新权限:
- 读取图片/照片:
android.permission.READ_MEDIA_IMAGES - 读取视频:
android.permission.READ_MEDIA_VIDEO - 读取音频:
android.permission.READ_MEDIA_AUDIO
2. 更新Manifest权限声明
保留旧权限兼容Android 12及以下版本,添加新权限适配Android 13+:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
3. 修改动态权限请求逻辑
根据系统版本选择对应权限请求:
private void readImages() { String permission; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { permission = Manifest.permission.READ_MEDIA_IMAGES; } else { permission = Manifest.permission.READ_EXTERNAL_STORAGE; } if (ContextCompat.checkSelfPermission(owner, permission) == PackageManager.PERMISSION_GRANTED) { loadImages(); } else { owner.requestPermission(this::loadImages, permission); } }
4. 验证请求码合法性
确保Permissions.permissionRequestCode()生成的请求码为0-65535之间的整数,超出范围会导致权限请求无法正确回调。
5. 模拟器环境校验
- 使用官方稳定版Android 13模拟器镜像,避免预览版或自定义镜像
- 清除应用数据并重启模拟器后重新测试
内容的提问来源于stack exchange,提问作者SDIDSA
相关产品推荐
相关产品推荐

