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(); } } } }