使用MediaStore获取设备内部存储音频仅返回一首的问题排查
问题排查与修复方案
1. 权限缺失(最可能的原因)
Android 6.0(API 23)及以上版本,访问公共存储的媒体文件需要动态申请权限,仅在Manifest中声明无法生效。
修复步骤:
- 在
AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+ 需替换为专属媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
- 在Activity中动态申请权限,并将媒体查询逻辑抽离到权限通过后执行:
private static final int STORAGE_PERMISSION_REQUEST = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_REQUEST); } else { loadAudioFiles(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == STORAGE_PERMISSION_REQUEST) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { loadAudioFiles(); } else { Toast.makeText(this, "需要存储权限才能读取音乐文件", Toast.LENGTH_SHORT).show(); } } } private void loadAudioFiles() { ListView audioView = findViewById(R.id.songView); ArrayList<String> audioList = new ArrayList<>(); String[] proj = {MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME}; Cursor audioCursor = getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj, null, null, null); if (audioCursor != null) { try { while (audioCursor.moveToNext()) { int nameIndex = audioCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME); audioList.add(audioCursor.getString(nameIndex)); } } finally { audioCursor.close(); } } ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, android.R.id.text1, audioList); audioView.setAdapter(adapter); }
2. Cursor安全关闭问题
原代码中,如果audioCursor为null,执行audioCursor.close()会触发空指针异常。将关闭操作放在try-finally块中,确保Cursor无论是否有数据都能被正确释放。
3. 筛选有效音乐文件(可选)
如果只想获取真正的音乐文件(排除铃声、系统提示音等非音乐类音频),可以在查询时添加筛选条件:
// 仅查询标记为音乐的音频文件 String selection = MediaStore.Audio.Media.IS_MUSIC + " = 1"; Cursor audioCursor = getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj, selection, null, null);
4. 关于内部存储的说明
注意:Android中MediaStore.Audio.Media.EXTERNAL_CONTENT_URI包含设备内置的公共存储和外接SD卡。如果你的需求是访问应用私有内部存储中的音乐文件,MediaStore无法直接访问,需要通过文件路径直接读取(比如getFilesDir()下的文件)。
内容的提问来源于stack exchange,提问作者Michelle
相关产品推荐
相关产品推荐

