zoukankan      html  css  js  c++  java
  • Android MediaPlayer 在 6.0 以上版本使用倍速播放功能说明

    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();
                }
            }
        }
    }
  • 相关阅读:
    【HTML5】html5在ie8及以下的兼容性问题
    【前端】从登录框看前端
    批量插入
    Mongodb地理空间索引
    Mongodb添加地理位置索引
    记一 次docker-compose build报错
    The method's class, com.google.common.collect.FluentIterable, is available from the following locations
    如果在chrome的新标签中继续打开开发工具
    设置idea 2018 的vmoptions无效
    spring boot(2):activiti整合
  • 原文地址:https://www.cnblogs.com/renhui/p/10906400.html
Copyright © 2011-2022 走看看