Android 本地音乐播放(读取系统媒体库 + MediaPlayer)

Android 本地音乐播放(读取系统媒体库 + MediaPlayer)

简介

本文介绍如何在 Android 中读取手机本地音乐并进行播放,包含:

  • ContentResolver.query() 参数说明
  • 常见查询条件写法
  • MediaPlayer 的正确初始化与释放
  • 权限与常见崩溃点修复

适用场景:播放设备中的本地音频文件(非在线流媒体)。


一、读取手机中的音乐

本地音频数据通常来自 MediaStore,通过 ContentResolver 查询:

java 复制代码
Cursor cursor = contentResolver.query(
        contentUri,
        projection,
        selection,
        selectionArgs,
        sortOrder
);

query() 常见参数说明:

  1. contentUri:查询目标表,例如外部音频库:
    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI

  2. projection:要返回的列(字段)

  3. selection:筛选条件(where 子句,不带 where 关键字)

  4. selectionArgs:给 selection? 占位符赋值

  5. 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

未授权时直接查询媒体库,通常会得到空结果或抛出异常。


四、总结

本地音乐播放的核心流程是:

  1. 通过 MediaStore 查询音频数据
  2. 组装可播放的 content:// Uri
  3. 使用 MediaPlayer 播放并正确释放资源

如果后续你需要,我可以再帮你把这篇文档继续升级成:

  • 可直接运行的完整示例(含权限申请)
  • 支持上一首/下一首、进度条、后台播放
  • 使用 ExoPlayer 的现代实现版本

github仓库代码

复制代码
https://github.com/lixiangoko/Musicimpleness
相关推荐
weixin_399380695 小时前
TongWeb7.0.4.9M11一键安装脚本(by sy)
java·spring
CallFay云起未来5 小时前
AI客服能不能减少人工回复?从重复咨询到人机协同的落地分析
java·大数据·人工智能·文心一言
我命由我123455 小时前
Android 开发 - 获取当前设备屏幕的旋转角度
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
Elastic 中国社区官方博客6 小时前
OpenTelemetry Java 扩展:无需分叉 agent 即可自定义追踪
java·大数据·运维·开发语言·数据库·人工智能·elasticsearch
京东云开发者6 小时前
上游给空、下游拿到 -1,我把故障一直追到了 commons-beanutils 的构造函数
java·ai编程
阿无,6 小时前
Java多线程面试题之AQS
java·开发语言
数据狐(Datafox)6 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
摇滚侠6 小时前
《SpringBoot 3:入门与应用实战》第 7 章 AOP 思想与实现 阅读笔记 15
java·spring boot·笔记
风尘小子6 小时前
java静态类使用@Value动态绑定环境变量
java
重生之后端学习7 小时前
239. 滑动窗口最大值[困难]✅
java·数据结构·算法·leetcode·职场和发展