Android MediaPlayer 在API 23即6.0版本开始支持倍速播放,下面我们来介绍一下如何使用MediaPlayer进行倍速播放。
一、核心接口
MediaPlayer.setPlaybackParams(PlaybackParams params) throws IllegalStateException, IllegalArgumentException
1. 接口说明
(1) 使用这个接口可以进行播放速率的设置。
(2) 播放器prepared状态之前调用这个方法不会更改播放器的状态。
(3) prepared状态之后设置速率0等同于调用pause(),当调用start恢复播放以后,将以原来的速率进行播放。
(4) prepared状态之后设置非0的速率等同于调用start()。
(5) 当播放器还未初始化或者已经被释放的时候设置会抛IllegalStateException的异常。
(6) 当参数不支持的时候会抛IllegalArgumentException的异常。
2. 设置时机要求
合法的时机:Initialized, Prepared, Started, Paused, PlaybackCompleted, Error
非法的时机:Idle, Stopped
二、使用示例
本例为悬浮弹窗播放View,在此基础上增加了倍速播放的测试逻辑,经测试,发现此API可用,且效果基本和ijk播放器一样。
public class FloatingPopupWindow implements SurfaceHolder.Callback {
// 弹窗宽度
private static final int POPUP_WINDOW_WIDTH = 567;
// 弹窗高度
private static final int POPUP_WINDOW_HEIGHT = 432;
private Context mContext;
private PopupWindow mPopupWindow;
private View mPopContentView;
private RelativeLayout mFloatingLayout;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
MediaPlayer mediaPlayer;
private boolean IsDouble = false;
private float lastX;
private float lastY;
public FloatingPopupWindow(Context context) {
mContext = context;
mPopContentView = LayoutInflater.from(mContext).inflate(R.layout.popup_window_floating, null);
mPopupWindow = new PopupWindow(mPopContentView, POPUP_WINDOW_WIDTH, POPUP_WINDOW_HEIGHT);
mFloatingLayout = mPopContentView.findViewById(R.id.floating_layout);
surfaceView = mPopContentView.findViewById(R.id.surface_view);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
mPopContentView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (event.getPointerCount() == 1) {
IsDouble = false;
}
if (!IsDouble) {
lastX = event.getRawX();
lastY = event.getRawY();
}
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() > 1) {
IsDouble = true;
}
if (!IsDouble) {
int deltaX = (int) (event.getRawX() - lastX);
lastX = event.getRawX();
int deltaY = (int) (event.getRawY() - lastY);
lastY = event.getRawY();
mPopupWindow.update(deltaX + (int) lastX - (POPUP_WINDOW_WIDTH / 2), deltaY + (int) lastY - (POPUP_WINDOW_HEIGHT / 2), -1, -1, true);
}
break;
}
return true;
}
});
mediaPlayer = new MediaPlayer();
}
/**
* 是否显示
*/
public boolean isShowing() {
return mPopupWindow.isShowing();
}
public void setPlayPath(String playPath) {
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(playPath);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Surface surface = holder.getSurface();
mediaPlayer.setSurface(surface);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
// 6.0及以后支持倍速,测试
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mp.setPlaybackParams(new PlaybackParams().setSpeed(0.75f));
}
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
dismiss();
}
});
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
private View mNowView; // 当前容器里面装载的View
/**
* 添加新View
*/
public void addView(View view) {
mNowView = view;
if (mFloatingLayout != null) {
mFloatingLayout.addView(view);
}
}
/**
* 获取当前正展示的View
*/
public View getNowView() {
return mNowView;
}
/**
* 移除所有的子布局
*/
public void removeAllView() {
if (mFloatingLayout != null) {
mFloatingLayout.removeAllViews();
}
}
/**
* 显示弹出框
*/
public void show(View view) {
if (isShowing()) {
return;
}
mPopupWindow.showAtLocation(view, Gravity.NO_GRAVITY, 0, 200);
}
/**
* 隐藏弹出框
*/
public void dismiss() {
if (mPopupWindow != null) {
if (mPopupWindow.isShowing()) {
mPopupWindow.dismiss();
}
}
}
}