Android 13应用首次启动未弹出存储权限请求的问题
Android 13 存储权限请求弹窗不显示的解决方案
问题根源
Android 13(API 33)重构了媒体存储权限体系,原READ_EXTERNAL_STORAGE权限在该版本下不再适用于音频、图片等媒体文件,必须使用对应细分权限(比如READ_MEDIA_AUDIO)。你的代码和Manifest仍在使用旧权限,导致系统无法触发权限请求弹窗。
修复方案
1. 更新AndroidManifest.xml权限配置
添加Android 13专属的音频读取权限,同时保留旧权限兼容低版本:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" android:minSdkVersion="33"/>
2. 适配不同版本的权限检查与请求逻辑
修改checkPermission和requestPermission方法,根据系统版本切换目标权限:
// 需添加导入:import android.os.Build; boolean checkPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // Android 13+ 检查音频媒体权限 return ContextCompat.checkSelfPermission(MainApp.this, Manifest.permission.READ_MEDIA_AUDIO) == PackageManager.PERMISSION_GRANTED; } else { // 低版本检查旧存储权限 return ContextCompat.checkSelfPermission(MainApp.this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; } } void requestPermission() { String[] permissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { permissions = new String[]{Manifest.permission.READ_MEDIA_AUDIO}; } else { permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}; } if (ActivityCompat.shouldShowRequestPermissionRationale(MainApp.this, permissions[0])) { Toast.makeText(MainApp.this, "需要读取音频权限才能加载本地音乐,请在设置中开启", Toast.LENGTH_LONG).show(); } ActivityCompat.requestPermissions(MainApp.this, permissions, 123); }
3. 处理权限授权后的逻辑
原代码请求权限后直接return,用户授权后不会重新加载音乐列表,需重写权限回调并抽离音乐加载逻辑:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 123) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 授权成功,重新加载音乐列表 loadMusicList(); } else { Toast.makeText(this, "未授予权限,无法加载本地音乐", Toast.LENGTH_SHORT).show(); textView.setVisibility(TextView.VISIBLE); } } } // 抽离音乐加载逻辑为独立方法 private void loadMusicList() { songsList.clear(); String[] projection = {MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.DURATION}; String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0"; Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, null, null); if (cursor != null) { while (cursor.moveToNext()) { AudioModel songData = new AudioModel(cursor.getString(1), cursor.getString(0), cursor.getString(2)); if (new File(songData.getPath()).exists()) { songsList.add(songData); } } cursor.close(); // 关闭Cursor避免内存泄漏 } if (songsList.size() == 0) { textView.setVisibility(TextView.VISIBLE); recyclerView.setVisibility(View.GONE); } else { textView.setVisibility(View.GONE); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(new MusicListAdapter(songsList, getApplicationContext())); } }
最后修改onCreate方法,调用抽离后的加载逻辑:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_app); recyclerView = findViewById(R.id.recylerView); textView = findViewById(R.id.warning); if (checkPermission()) { loadMusicList(); } else { requestPermission(); } }
内容的提问来源于stack exchange,提问作者NAUFAL_ ARZ
相关产品推荐
相关产品推荐

