Android 本地音乐播放(读取系统媒体库 + MediaPlayer)
简介
本文介绍如何在 Android 中读取手机本地音乐并进行播放,包含:
ContentResolver.query()参数说明- 常见查询条件写法
MediaPlayer的正确初始化与释放- 权限与常见崩溃点修复
适用场景:播放设备中的本地音频文件(非在线流媒体)。
一、读取手机中的音乐
本地音频数据通常来自 MediaStore,通过 ContentResolver 查询:
java
Cursor cursor = contentResolver.query(
contentUri,
projection,
selection,
selectionArgs,
sortOrder
);
query() 常见参数说明:
-
contentUri:查询目标表,例如外部音频库:
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI -
projection:要返回的列(字段) -
selection:筛选条件(where子句,不带where关键字) -
selectionArgs:给selection中?占位符赋值 -
sortOrder:排序方式
1) 常用 URI(修复原文拼写错误)
原文中的 Media.EXTERNL_CONTENT_URL 是错误写法,正确为:
java
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
2) 推荐查询字段
java
String[] projection = new String[]{
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.SIZE
};
说明:
MediaStore.Audio.Media.DATA(_data)在高版本中已不推荐直接使用,建议优先使用content://类型的Uri来播放。
3) 推荐筛选条件
java
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.DATE_ADDED + " DESC";
复杂筛选建议使用 selectionArgs,避免拼接字符串导致可读性差或出错。
4) 查询示例(含资源释放)
java
List<Uri> musicUris = new ArrayList<>();
Uri contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
try (Cursor cursor = getContentResolver().query(
contentUri,
projection,
selection,
null,
sortOrder
)) {
if (cursor != null) {
int idIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID);
while (cursor.moveToNext()) {
long id = cursor.getLong(idIndex);
Uri songUri = ContentUris.withAppendedId(contentUri, id);
musicUris.add(songUri);
}
}
}
二、使用 MediaPlayer 播放
下面给出一个更安全的初始化与播放流程:
java
private RecyclerView rcList;
private MediaPlayer mediaPlayer;
private final List<Uri> musicUris = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rcList = findViewById(R.id.rc_list);
rcList.setLayoutManager(new LinearLayoutManager(this));
loadMusic(); // 查询本地音乐并填充 musicUris
if (!musicUris.isEmpty()) {
mediaPlayer = MediaPlayer.create(this, musicUris.get(0));
}
}
private void play() {
if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
private void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
}
修复点(对应原文常见 bug)
MediaPlayer.create(this, Uri.parse(path))并不总是可靠,优先使用content://的Uri- 播放前需要判空,避免
musicList.get(0)越界 - 在
onDestroy()中调用release(),避免内存泄漏和句柄占用
三、权限说明
- Android 6.0+ 需运行时权限(旧版本常见是读取存储权限)
- Android 13+ 推荐使用
READ_MEDIA_AUDIO
未授权时直接查询媒体库,通常会得到空结果或抛出异常。
四、总结
本地音乐播放的核心流程是:
- 通过
MediaStore查询音频数据 - 组装可播放的
content://Uri - 使用
MediaPlayer播放并正确释放资源
如果后续你需要,我可以再帮你把这篇文档继续升级成:
- 可直接运行的完整示例(含权限申请)
- 支持上一首/下一首、进度条、后台播放
- 使用
ExoPlayer的现代实现版本
https://github.com/lixiangoko/Musicimpleness