Android 媒体播放架构
在 Android 10 (API 29) 及更高版本,Google 推荐使用 Media3 库来处理所有媒体播放相关任务,它整合了旧版 MediaPlayer、ExoPlayer 和 MediaSession 的优点,提供了更强大、更灵活、更统一的解决方案。

- ExoPlayer:
Media3的核心播放引擎,它高度可定制,支持各种媒体格式(如 DASH, HLS, SmoothStreaming),并且能更好地适应不同的网络条件。 - MediaSession: 负责管理媒体会话,允许你的应用与其他系统组件(如通知、锁屏媒体控件、Android Auto)进行交互。
- MediaLibraryService: 一个服务,用于管理你的音乐库,让系统媒体浏览器(如 Google Assistant)可以发现和控制你的应用。
对于简单的需求,你也可以使用 Android 原生的 MediaPlayer,但 Media3 是未来的方向,强烈推荐。
使用原生 MediaPlayer (简单直接)
MediaPlayer 非常易于使用,适合简单的播放、暂停、停止等操作。
添加网络权限
在 AndroidManifest.xml 中必须声明访问互联网的权限:
<uses-permission android:name="android.permission.INTERNET" />
为了安全起见,建议在 <application> 标签中添加 android:usesCleartextTraffic="true",如果你的音乐 URL 是 http 而非 https。

基本播放代码示例
import android.media.MediaPlayer
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class MediaPlayerActivity : AppCompatActivity() {
private var mediaPlayer: MediaPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_media_player)
val playButton: Button = findViewById(R.id.btn_play)
val pauseButton: Button = findViewById(R.id.btn_pause)
val stopButton: Button = findViewById(R.id.btn_stop)
val musicUrl = "https://example.com/your-music.mp3" // 替换为你的音乐URL
playButton.setOnClickListener {
// mediaPlayer 还没创建或者已经播放完毕
if (mediaPlayer == null) {
try {
mediaPlayer = MediaPlayer().apply {
setDataSource(musicUrl)
// 异步准备,避免阻塞UI线程
prepareAsync()
setOnPreparedListener { mp ->
// 准备完成后开始播放
mp.start()
Toast.makeText(this@MediaPlayerActivity, "开始播放", Toast.LENGTH_SHORT).show()
}
setOnCompletionListener { mp ->
// 播放完成
mp.release()
mediaPlayer = null
Toast.makeText(this@MediaPlayerActivity, "播放完成", Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(this, "播放失败: ${e.message}", Toast.LENGTH_LONG).show()
}
} else {
mediaPlayer?.start()
}
}
pauseButton.setOnClickListener {
mediaPlayer?.pause()
Toast.makeText(this, "暂停播放", Toast.LENGTH_SHORT).show()
}
stopButton.setOnClickListener {
mediaPlayer?.stop()
mediaPlayer?.release()
mediaPlayer = null
Toast.makeText(this, "停止播放", Toast.LENGTH_SHORT).show()
}
}
override fun onDestroy() {
super.onDestroy()
// 在 Activity 销毁时释放资源,防止内存泄漏
mediaPlayer?.release()
mediaPlayer = null
}
}
MediaPlayer 的优缺点
- 优点: API 简单,上手快,无需额外依赖。
- 缺点: 功能有限,定制性差,对高级流媒体协议支持不佳,资源管理需要手动小心,否则容易出错。
使用 Google Media3 (推荐,功能强大)
Media3 是现代 Android 应用的首选,它能提供更流畅的播放体验、更好的性能和更丰富的功能。
添加依赖
在 app/build.gradle.kts (或 app/build.gradle) 文件中添加 Media3 依赖:
// build.gradle.kts
dependencies {
// Media3 核心、播放器和 UI 组件
implementation("androidx.media3:media3-exoplayer:1.4.1") // 使用最新版本
implementation("androidx.media3:media3-exoplayer-hls:1.4.1") // 如果播放 HLS 流
implementation("androidx.media3:media3-ui:1.4.1") // 播放器 UI 组件
implementation("androidx.media3:media3-session:1.4.1") // MediaSession 支持
}
基本播放代码示例
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
import com.example.myapp.R // 替换成你的包名
class Media3Activity : AppCompatActivity() {
private var exoPlayer: ExoPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_media3)
val playButton: Button = findViewById(R.id.btn_play)
val pauseButton: Button = findViewById(R.id.btn_pause)
val musicUrl = "https://example.com/your-music.mp3" // 替换为你的音乐URL
playButton.setOnClickListener {
if (exoPlayer == null) {
initializePlayer(musicUrl)
} else {
exoPlayer?.play()
}
}
pauseButton.setOnClickListener {
exoPlayer?.pause()
}
}
private fun initializePlayer(url: String) {
// 创建 ExoPlayer 实例
exoPlayer = ExoPlayer.Builder(this).build().also { player ->
// 设置播放器到视图(如果有的话,PlayerView)
// playerView.player = player
// 创建 MediaItem
val mediaItem = MediaItem.fromUri(url)
// 设置要播放的媒体项
player.setMediaItem(mediaItem)
// 添加监听器
player.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) {
when (playbackState) {
Player.STATE_BUFFERING -> Toast.makeText(this@Media3Activity, "缓冲中...", Toast.LENGTH_SHORT).show()
Player.STATE_READY -> {
Toast.makeText(this@Media3Activity, "准备就绪,开始播放", Toast.LENGTH_SHORT).show()
player.play() // 自动播放
}
Player.STATE_ENDED -> Toast.makeText(this@Media3Activity, "播放结束", Toast.LENGTH_SHORT).show()
}
}
})
// 准备播放
player.prepare()
}
}
override fun onStart() {
super.onStart()
// Activity 可见,可以在这里恢复播放
}
override fun onStop() {
super.onStop()
// Activity 不可见,暂停播放以节省资源
exoPlayer?.pause()
}
override fun onDestroy() {
super.onDestroy()
// 释放 ExoPlayer 资源
exoPlayer?.release()
exoPlayer = null
}
}
Media3 的优势
- 高性能: 基于
ExoPlayer,经过高度优化。 - 高度可定制: 可以自定义加载器、渲染器、源工厂等。
- 协议支持: 内置对 DASH, HLS, SmoothStreaming 等现代流媒体协议的支持。
- 集成度高: 与
MediaSession无缝集成,轻松实现通知和锁屏控制。 - 生命周期感知: 更容易与 Activity/Fragment 的生命周期结合。
关键考量与最佳实践
无论选择哪种方案,以下几点都非常重要:
生命周期管理
播放器(尤其是 MediaPlayer)是重量级资源,必须在 Activity/Fragment 的生命周期中正确创建和释放。

- 创建: 在
onCreate或onStart中初始化。 - 暂停: 在
onStop中暂停播放,避免后台播放消耗资源。 - 释放: 在
onDestroy中调用release()或player.release(),彻底释放资源,防止内存泄漏。
网络处理
- 使用
HttpURLConnection或 OkHttp: 对于MediaPlayer,最好使用自定义的DataSource来通过HttpURLConnection或 OkHttp 获取数据,这样可以更好地处理请求头、缓存和重试逻辑。 Media3内置优化:Media3已经内置了强大的网络层,它会自动处理缓冲、预加载和基于网络状况的码率切换。
缓冲与用户体验
- 异步准备: 永远不要在主线程上调用
prepare()或prepareSync(),这会导致 ANR(应用无响应),使用prepareAsync()。 - 显示缓冲状态: 在播放器进入
STATE_BUFFERING状态时,向用户显示一个缓冲指示器(如一个转圈的进度条)。 - 错误处理: 妥善处理播放过程中的错误(如网络中断、文件损坏),并向用户反馈。
后台播放与通知
要让音乐在后台持续播放,你需要:
- 启动一个
Service: 将播放器逻辑移到Service中,这样即使应用被关闭,服务也能在后台运行。 - 创建通知: 在
Service中创建一个前台通知,这不仅能防止系统在低内存时杀死你的服务,还能为用户提供播放控制按钮(播放/暂停、上一曲、下一曲)。 - 使用
MediaSession:MediaSession是实现这一切的关键,它会将你的播放器状态和控件广播给系统,系统会自动将其显示在通知和锁屏上。
总结与建议
| 特性 | MediaPlayer |
Media3 (推荐) |
|---|---|---|
| 易用性 | 高,API 简单 | 中等,概念稍多,但文档清晰 |
| 功能 | 基础播放 | 强大,支持所有现代流媒体协议 |
| 性能 | 一般 | 优秀,高度优化 |
| 定制性 | 差 | 极高,可定制每个组件 |
| 后台播放 | 需要手动实现 Service 和通知 | 内置支持,通过 MediaSession 轻松实现 |
| 依赖 | 无需额外依赖 | 需要添加 Media3 库 |
给你的建议:
- 如果你的 App 只需要一个简单的音效播放,或者你只是想快速实现一个功能,可以考虑使用
MediaPlayer。 - 如果你的 App 是一个音乐播放器、播客应用或任何需要高质量、稳定播放体验的应用,请毫不犹豫地选择
Media3,它虽然学习曲线稍陡,但能为你省去大量处理复杂情况的麻烦,并为你提供专业级的播放体验,这是 Google 官方推荐的现代解决方案。
