自定义 影片播放器——MediaPlayer 与SurfaceView

本文介绍如何使用MediaPlayer在Android上创建视频播放器。通过SurfaceView显示视频,实现视频大小调整及事件监听等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本示例使用 使用MediaPlayer  制作一个 视频播放器 ,可指定视频的大小、预览的模式之外,还提供对 prepare,OnCompletionListener  等事件的判断。

通过创建SurfaceView  视图与控制SurfaceView 的 SurfaceHolder  对象,搭配 MediaPlayer  的 setDisplay()  方法来指定要将图像显示于指定的 SurfaceView 之上

要在Activity 里配置 SurfaceView ,必须实现 SurfaceHolder.Callback接口

注意这里 <SurfaceView  android:id="@+id/mSurfaceView1"
                            android:layout_width="320px"
                            android:layout_height="240px"/>, 虽然设置宽高属性为320X240 (pixel),

但在java类中 如果没有以下一行

mSurfaceHolder01.setFixedSize(176,144);

播放视频时会以原影片大小播放,也就是说单纯设置320 X 240 没有作用, SurfaceView 其余范围会以黑底呈现

示意图如下:

 

具体用法请参见 EX07_14 工程

MediaPlayer 类是非常系统化的,需要按特定顺序调用操作来正确初始化媒体播放器, 并让它准备回放. 以下总结了一些特征:

1   设置了 MediaPlayer 的数据源以后,就不能随意更改它,  必须创建一个新MediaPlayer 对象或调用 reset()  方法来重新初始化播放器的状态

2    调用prepare()  之后,可以调用getCurrentPosition()、getDuration()和isPlaying()  来获取播放器的当前状态。也可以在调用prepare()  之后调用setLooping() 和 setVolume()

3    调用start()之后,可以调用pause()、stop()、seekTo().

4   每个 MediaPlayer  创建一个新线程,要确保使用播放器完成后调用release(), 对于视频回放,必须手动完成此工作。


### 使用 MediaPlayerSurfaceView 和 SurfaceHolder.Callback 实现视频播放器 #### 设计思路 为了构建一个基于 `MediaPlayer` 和 `SurfaceView` 的自定义视频播放器,设计的核心在于管理好各个组件之间的交互。具体来说: - 创建并配置 `MediaPlayer` 对象用于处理音频/视频文件的加载回放操作。 - 利用 `SurfaceView` 组件作为视频渲染的目标窗口。 - 通过实现 `SurfaceHolder.Callback` 接口监听 `SurfaceView` 生命周期事件(创建、改变大小、销毁),从而同步调整 `MediaPlayer` 状态。 #### 关键方法说明 当 `SurfaceView` 被创建,在 `surfaceCreated()` 中初始化 `MediaPlayer` 并准备好它所使用的数据源以及关联至当前视图持有的 `SurfaceHolder`[^2]。 一旦准备工作完成,则可以在 `onPrepared(MediaPlayer mp)` 回调函数内启动实际的媒体流传输过程;而每当检测到视频帧尺寸发生变化,应相应更新容器控件的实际显示区域以匹配新参数——这通常是在 `onVideoSizeChanged(mp, width, height)` 函数里执行的操作。 最后,在 `surfaceDestroyed(SurfaceHolder holder)` 方法中确保及清理不再需要的对象实例及其占用资源,防止内存泄漏等问题发生。 #### 示例代码 下面给出一段简化版的 Java 代码片段,展示了上述概念的具体实践方式: ```java public class VideoPlayerActivity extends AppCompatActivity implements SurfaceHolder.Callback { private MediaPlayer mediaPlayer; private SurfaceView surfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_player); surfaceView = findViewById(R.id.surface_view); surfaceView.getHolder().addCallback(this); // 注册回调接口 // 设置其他必要的属性... } @Override public void surfaceCreated(SurfaceHolder holder) { try { Uri videoUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.samplevideo); mediaPlayer = new MediaPlayer(); mediaPlayer.setDataSource(getApplicationContext(), videoUri); mediaPlayer.setDisplay(holder); mediaPlayer.prepareAsync(); // 异步准备 mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); // 开始播放 } }); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { // 处理播放结束后的逻辑 } }); mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { // 错误处理机制 return false; } }); mediaPlayer.setOnVideoSizeChangedListener((mp, w, h) -> { // 更新界面布局适应新的宽高比例 }); } catch (IOException e) { Log.e("VideoPlayer", "Unable to play video"); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} @Override public void surfaceDestroyed(SurfaceHolder holder) { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); } if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; // 防止泄露 } } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值