核心概念
一个 Android 网络视频播放器主要涉及以下几个关键技术点:

- 网络请求:从服务器获取视频数据,通常使用
HttpURLConnection或第三方库如 OkHttp。 - 本地缓存:为了提升播放体验(如快进、切换清晰度)和节省流量,需要将下载的视频片段缓存到本地。
ExoPlayer和IJKPlayer都内置了缓存功能。 - 视频解码:将网络下载的视频流(如 MP4, HLS, DASH)解码成 Android 系统可以理解的 YUV 或 RGB 帧数据,这通常使用硬解码(GPU)以提高性能。
- 视频渲染:将解码后的帧数据绘制到屏幕上,可以使用
SurfaceView、TextureView或Surface。 - 播放控制:实现播放、暂停、进度条拖动、音量调节、全屏切换等交互功能。
主流播放器库选择
直接从零开始实现上述所有功能非常复杂且容易出错,业界普遍使用成熟的第三方播放器库,以下是几个最主流的选择:
| 库名 | 开发者 | 特点 | 适用场景 |
|---|---|---|---|
| ExoPlayer | Google (官方) | 强烈推荐,高度可定制、支持现代流媒体协议(HLS, DASH)、性能优异、生命周期管理良好、支持动态自适应码率。 | 新项目、对性能和协议支持有高要求的应用。 |
| IJKPlayer | Bilibili (基于 FFmpeg) | 功能强大,支持的格式和协议非常广泛(几乎无所不包),基于 FFmpeg,解码能力强。 | 需要播放各种“奇葩”格式、对兼容性要求极高的场景。 |
| MediaPlayer | Android (系统自带) | 简单易用,系统级集成,功耗可能较低,但功能有限,扩展性差,对 HLS/DASH 支持不佳。 | 简单的、固定 MP4 文件的播放需求。 |
- 新项目首选
ExoPlayer,它是 Google 的亲儿子,代表了未来的方向,文档完善,社区活跃。 - 如果你的应用需要播放大量非标准格式或老旧格式,可以考虑
IJKPlayer,但它的集成和调试会更复杂。 MediaPlayer只适合非常简单的场景,不推荐用于复杂的网络视频播放。
使用 ExoPlayer 实现网络视频播放器 (详细步骤)
下面我们以最推荐的 ExoPlayer 为例,手把手教你实现一个功能完整的网络视频播放器。
步骤 1:添加依赖
在 app/build.gradle 文件中添加 ExoPlayer 的依赖,通常推荐使用 media2 版本,因为它更现代化。
dependencies {
// ExoPlayer Core
implementation 'androidx.media3:media3-exoplayer:1.4.1' // 请使用最新版本
// ExoPlayer MediaSession (用于与媒体通知和控制中心集成)
implementation 'androidx.media3:media3-session:1.4.1'
// ExoPlayer UI (提供标准的播放器 UI 组件)
implementation 'androidx.media3:media3-ui:1.4.1'
// OkHttp (用于网络请求,ExoPlayer 内部使用)
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
}
步骤 2:添加网络权限
在 AndroidManifest.xml 中添加网络访问权限。

<uses-permission android:name="android.permission.INTERNET" />
步骤 3:布局文件 activity_main.xml
创建一个简单的布局,包含一个 PlayerView (这是 ExoPlayer 提供的带 UI 控件的视图)。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.media3.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:use_controller="true"
app:show_buffering="when_playing"
app:resize_mode="fit" />
</RelativeLayout>
app:use_controller="true":显示播放/暂停、进度条、音量等控制器。app:show_buffering="when_playing":在播放时显示缓冲指示器。app:resize_mode="fit":视频缩放模式,还有fill,zoom等选项。
步骤 4:Java/Kotlin 代码实现
在 MainActivity.kt (或 MainActivity.java) 中编写逻辑。
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
class MainActivity : AppCompatActivity() {
private lateinit var playerView: PlayerView
private var exoPlayer: ExoPlayer? = null
// 示例视频 URL (使用一个公开的测试视频)
private val videoUrl = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
playerView = findViewById(R.id.player_view)
// 初始化 ExoPlayer
initializePlayer()
}
@UnstableApi // ExoPlayer 的某些 API 需要这个注解
private fun initializePlayer() {
// 1. 创建 ExoPlayer 实例
exoPlayer = ExoPlayer.Builder(this).build().also { player ->
// 2. 将 PlayerView 与 ExoPlayer 关联
playerView.player = player
// 3. 创建 MediaItem
val mediaItem = MediaItem.fromUri(videoUrl)
// 4. 准备并播放
player.setMediaItem(mediaItem)
player.prepare()
player.playWhenReady = true // 自动播放
}
// 监听播放器状态
exoPlayer?.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) {
when (playbackState) {
Player.STATE_BUFFERING -> {
Toast.makeText(this@MainActivity, "正在缓冲...", Toast.LENGTH_SHORT).show()
}
Player.STATE_READY -> {
Toast.makeText(this@MainActivity, "准备就绪,可以播放", Toast.LENGTH_SHORT).show()
}
Player.STATE_ENDED -> {
Toast.makeText(this@MainActivity, "播放结束", Toast.LENGTH_SHORT).show()
}
}
}
})
}
// 在 Activity 生命周期中正确管理播放器
override fun onStart() {
super.onStart()
if (exoPlayer == null) {
initializePlayer()
}
}
override fun onResume() {
super.onResume()
// 当返回前台时,如果用户之前暂停了,则恢复播放
exoPlayer?.playWhenReady = true
}
override fun onPause() {
super.onPause()
// 当暂停或进入后台时,暂停播放以节省资源
exoPlayer?.playWhenReady = false
}
override fun onStop() {
super.onStop()
releasePlayer()
}
override fun onDestroy() {
super.onDestroy()
releasePlayer()
}
private fun releasePlayer() {
exoPlayer?.let { player ->
playerView.player = null
player.release()
exoPlayer = null
}
}
}
代码解析:
initializePlayer():核心初始化方法。ExoPlayer.Builder(this).build():创建ExoPlayer实例。playerView.player = player:将PlayerView和Player绑定。MediaItem.fromUri(videoUrl):将视频 URL 封装成MediaItem。player.setMediaItem(),player.prepare(),player.playWhenReady = true:设置媒体、准备播放器并开始播放。
Player.Listener:通过监听器可以获取播放器的各种状态,如缓冲、准备就绪、播放结束等,便于进行 UI 反馈。- 生命周期管理:至关重要!
onStart()/onResume():当 Activity 可见时,确保播放器已初始化并准备播放。onPause()/onStop():当 Activity 不可见时,暂停播放,避免

