前言
媒体是指传播信息的媒介,在Android设备上包括图片、音频和视频
三个关键点:信息、媒介和传播。对设备而言就是内容编解码、容器格式和网络协议
在Android系统中播放音频和视频主要是以下两个类:
MediaPlayer,播放音频和视频的逻辑由它实现。
AudioManager,管理音频资源和在设备上的输出。
MediaPlayer播放流程图:
媒体播放器
private MediaPlayer mediaPlayer;
private void play(String path) {
if (null == mediaPlayer) {
//初始化播放器
mediaPlayer = new MediaPlayer();
//设置准备监听
mediaPlayer.setOnPreparedListener(onPreparedListener);
//设置错误监听
mediaPlayer.setOnErrorListener(onErrorListener);
//设置结束监听
mediaPlayer.setOnCompletionListener(onCompletionListener);
} else {
mediaPlayer.reset();
}
// 处于 idle 状态
// 设置播放的媒体源
try {
mediaPlayer.setDataSource(path);
//处于初始化完毕状态
//异步准备资源
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
// 媒体播放的准备结果监听
private MediaPlayer.OnPreparedListener onPreparedListener = new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// 准备完成 --- 控制媒体的播放 ( 播放、设置播放位置、获取媒体的总时间、暂停、停止 )
mp.start();
}
};
// 解码错误监听
private MediaPlayer.OnErrorListener onErrorListener = new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
};
// 播放结束监听
private MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
}
};
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
// 如果是第一次播放,那么设置音频文件准备 MediaPlayer 对象
if (mediaPlayer == null) {
//播放路径
play("/mnt/sdcard/media/ytjy.mp3");
} else {
if (null != mediaPlayer && !mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
break;
case R.id.btn_pause:
if (null != mediaPlayer && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
break;
}
}
媒体播放是很耗资源的,当不用时,记得通过以下代码释放它:
private void stop(){
if(mediaPlayer!=null){
mediaPlayer.stop();
// 释放资源 ( 释放库中的 c 对象 )
mediaPlayer.release();
mediaPlayer = null;
}
}
根据情况在 onStart()、onResume()、onRestart() 方法中创建,在 onStop()、onDestory() 方法中释放。
异步准备资源
资源的解码是比较耗时的,尤其是来自网络的视频,缓冲不稳定且解码量大。不建议将 prepare() 方法放在UI线程中处理,因为阻塞时间过长就会引起用户反感。系统提供了另一个方法prepareAsync() 来替代它, 先通setOnPreparedListener() 方法给MediaPlayer设置监听,当资源准备完成后将回调MediaPlayer.OnPreparedListener 接口的 onPrepared() 方法,执行你写的播放逻辑。
视频播放 VideoView
基于 MediaPlayer 以及 SurfaceView 实现的视频播放视图
使用 android:screenOrientation 属性来设置Activity的屏幕方向:
<activity android:name=".VideoActivity"
android:screenOrientation="landscape"></activity>
landscape 横屏
portrait 竖屏
sensor 跟传感器方向一致 ( 竖着拿就是竖屏,横着拿就是横屏 )
xml:
<VideoView
android:id="@+id/video"
android:layout_width="match_parent"
android:layout_height="match_parent" />
java:
VideoView videoView = findViewById(R.id.video);
// 设置路径
videoView.setVideoPath("/mnt/sdcard/media/gee.mp4");
// 设置控制器
videoView.setMediaController(new MediaController(this));
开始
videoView.start();
暂停
videoView.pause()
停止
videoView.stopPlayback();
TextureView+MediaPlayer 定义视频播放器
TextureView 在 android3.0 之后提出,是 SurfaceView 的升级版,使用时需要开启硬件加速
Application 级别
<application
android:hardwareAccelerated="true"
...
</application>
Activity 级别
<activity android:name=".MusicActivity" android:hardwareAccelerated="false"/>
<activity android:name=".VideoPlayActivity" android:hardwareAccelerated="true"> </activity>
定义视频播放器:
TextureView textureView = findViewById(R.id.texture);
// 监听 Surface 的创建情况
textureView.setSurfaceTextureListener(surfaceTextureListener);
//Surface 监听
private TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {
//Surface 创建成功
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
displaySurface = new Surface(surface);
// 开始播放视频
playVideo("/mnt/sdcard/media/gee.mp4");
}
//Surface 大小发生变化
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
//Surface 被销毁
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
return true;
}
//Surface 内容更新
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
MediaPlayer 播放视频的关键方法
mediaPlayer.setSurface(displaySurface); // 针对 TextureView 来显示画面的
//mediaPlayer.setDisplay(holder); // 针对 SurfaceView 来显示画面的
完整的视频播放流程
private void playVideo(String path) {
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
// 设置基本的监听
mediaPlayer.setOnPreparedListener(onPreparedListener);
mediaPlayer.setOnErrorListener(onErrorListener);
mediaPlayer.setOnCompletionListener(onCompletionListener);
// 设置视频画面大小的监听
mediaPlayer.setOnVideoSizeChangedListener(
onVideoSizeChangedListener);
// 设置播放中不关闭屏幕
mediaPlayer.setScreenOnWhilePlaying(true);
} else {
mediaPlayer.reset();
}
// 设置视频的显示画面
mediaPlayer.setSurface(displaySurface); // 针对 TextureView 来显示画面的
try {
mediaPlayer.setDataSource(path);
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
private MediaPlayer.OnPreparedListener onPreparedListener = new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// 准备成功
mp.start();
}
};
private MediaPlayer.OnErrorListener onErrorListener = new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
};
private MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
}
};
// 视频尺寸大小变化监听
private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
}
};