前言
Android多媒体中的——MediaPlayer,我们可以通过这个API来播放音频和视频 该类是Androd多媒体框架中的一个重要组件,通过该类,我们可以以最少的步骤来获取,解码 和播放音视频。它支持三种不同的媒体来源:
- 本地资源
- 内部的URI,比如你可以通过ContentResolver来获取
- 外部URL(流) 对于Android所支持的的媒体格式列表
一、MedaiPlayer状态图
音频/视频文件和流的播放控制作为状态机进行管理。下图显示了受支持的播放控制操作驱动的 MediaPlayer 对象的生命周期和状态。椭圆表示 MediaPlayer 对象可能驻留的状态。弧表示驱动对象状态转换的播放控制操作。有两种类型的弧。带单箭头的弧表示同步方法调用,带双箭头的弧表示异步方法调用。  从这个状态图中,可以出MediaPlayer对象具有以下状态:
-
MediaPlayer在使用new或者reset()之后,它处于idle状态,并且在release()被调用之后,它处于结束状态。 当处于除End状态外,都可以调用reset()把Mediaplayer置为idle状态。
当MediaPlayer对象不再使用后,需要调用relase()释放资源,使它转为End状态。
-
通过注册的setOnErrorListener(android.media.MediaPlayer.OnErrorListener)事件可以获取到一些编程错误信息。 -
idle状态状态下调用setDataSource(),将idle状态的MediaPlayer对象转到initialized状态。(在其他状态调用setDataSource会抛出IllegalStateException错误。) -
MediaPlayer需要进入Prepared状态后,才能开始播放。 可以通过两种方式到达Prepared状态:
1、同步,调用prepare(),调用返回后将对象转移到Prepared状态。
2、异步,调用prepareAsync(),首先在调用返回后(几乎立即发生)进入Preparing状态,而内部播放器引擎继续处理其余的准备工作,直到准备工作完成。之后会触发setOnPreparedListener回调。
-
要开始播放,start()必须调用,调用start()成功后进入started状态。 -
调用pause(),进入Paused状态。 -
调用stop(),进入Stopped状态,stop状态后需要进入Prepared状态才能开始播放。 -
当播放到达流的末尾时,播放完成。 需要setLooping为false,才会进入PlaybackCompleted。
setLooping为true,,MediaPlayer 对象会会保持在Started状态
-
在PlaybackCompleted 状态下,调用start()可以从音频/视频源的开头重新开始播放。
二、案例
package com.cs.testmediaplayer;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
SurfaceView mSvVideoPlayer;
private MediaPlayer mMediaPlayer;
private int mPosition = 0;
private boolean hasActiveHolder = false;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSvVideoPlayer = findViewById(R.id.sv_video_player);
playVideo();
}
public void playVideo() {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
mSvVideoPlayer.setVisibility(View.VISIBLE);
boolean mHardwareDecoder = false;
mSvVideoPlayer.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSvVideoPlayer.getHolder().setFixedSize(getScreenWidth(), getScreenHeight());
mSvVideoPlayer.getHolder().setKeepScreenOn(true);
mSvVideoPlayer.getHolder().addCallback(new SurFaceCallback());
}
}
private final class SurFaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (mMediaPlayer == null) {
return;
}
if (!hasActiveHolder) {
play(mPosition);
hasActiveHolder = true;
}
if (mPosition > 0) {
play(mPosition);
mPosition = 0;
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mMediaPlayer == null) {
return;
}
mMediaPlayer.setScreenOnWhilePlaying(true);
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mPosition = mMediaPlayer.getCurrentPosition();
}
}
private void play(int position) {
try {
mMediaPlayer.reset();
mMediaPlayer.setDisplay(mSvVideoPlayer.getHolder());
mMediaPlayer.setDataSource("https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv");
Log.d(TAG, "setDataSource: ");
mMediaPlayer.stop();
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnBufferingUpdateListener(new BufferingUpdateListener());
mMediaPlayer.setOnPreparedListener(new PreparedListener(position));
mMediaPlayer.setOnCompletionListener(new CompletionListener());
} catch (Exception e) {
e.printStackTrace();
}
}
}
private final class BufferingUpdateListener implements MediaPlayer.OnBufferingUpdateListener {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mPosition = mMediaPlayer.getCurrentPosition();
} else {
mMediaPlayer.start();
mMediaPlayer.seekTo(mPosition);
}
}
mMediaPlayer.stop();
}
}
private final class PreparedListener implements MediaPlayer.OnPreparedListener {
private int position;
public PreparedListener(int position) {
Log.d(TAG, "PreparedListener ");
this.position = position;
mMediaPlayer.start();
}
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "onPrepared:start ");
mMediaPlayer.start();
if (position > 0) {
mMediaPlayer.seekTo(position);
}
}
}
private final class CompletionListener implements MediaPlayer.OnCompletionListener {
@Override
public void onCompletion(MediaPlayer mp) {
}
}
@Override
public void onDestroy() {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mPosition = mMediaPlayer.getCurrentPosition();
}
mMediaPlayer.release();
mMediaPlayer = null;
}
super.onDestroy();
}
private int getScreenWidth() {
return ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
}
private int getScreenHeight() {
return ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
.getHeight();
}
}
|