android 播放视频常见问题

来源:互联网 发布:知乎@公众号提问 编辑:程序博客网 时间:2024/05/22 11:45

在android 开发中常见到视频播放的问题,在常规的视频中 有直接用videoView + MediaController 或者 mediaController + serfercie holder

常见的问题

1 在播放中如何处理播放器的横屏切换 和 播放器上的文案显示的布局变化

在activity 中 设置

 android:configChanges="orientation|screenSize"

这样在旋转中,activity 就不会重建

重写系统方法

 public void onConfigurationChanged(Configuration newConfig) {        // TODO Auto-generated method stub        super.onConfigurationChanged(newConfig);        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {            initVideoLandLayout();        } else {            initVideoPortLayout();        }    }

通过 判断 newConfig.orientation 来判断 当前是横屏还是竖屏, 这个是在看视频的过程中去判断是不是横屏还是竖屏,在我门一开始播放视频的时候,也可以去判断,具体的处理方法是

 private void initVideoPlayerLayout() {        DisplayMetrics dm = new DisplayMetrics();        getWindowManager().getDefaultDisplay().getMetrics(dm);        width = dm.widthPixels;        heigh = dm.heightPixels;        if (width / heigh > 0) { // 横屏            initVideoLandLayout();            fullscreen = true;        }        if (width / heigh == 0) { //竖屏            initVideoPortLayout();        }    }

在具体变化播放器上的布局的时候我们可以动态的去更换

    private void initVideoPortLayout() {        RelativeLayout.LayoutParams videoLp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);        videoLp.addRule(RelativeLayout.CENTER_IN_PARENT);        videoView.setLayoutParams(videoLp);        videoView.start();        RelativeLayout.LayoutParams hotelInfoLp = new RelativeLayout.LayoutParams(DeviceInfoUtil.getPixelFromDip(200), DeviceInfoUtil.getPixelFromDip(55));        hotelInfoLp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);        hotelInfoLp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);        hotelInfoLp.rightMargin = DeviceInfoUtil.getPixelFromDip(8);        hotelInfoLp.bottomMargin = DeviceInfoUtil.getPixelFromDip(90);        mHotelInfoLayout.setLayoutParams(hotelInfoLp);    }

这是竖屏处理

   private void initVideoLandLayout() {        RelativeLayout.LayoutParams layoutParams =                new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);        videoView.setLayoutParams(layoutParams);        RelativeLayout.LayoutParams hotelInfoLp = new RelativeLayout.LayoutParams(DeviceInfoUtil.getPixelFromDip(200), DeviceInfoUtil.getPixelFromDip(55));        hotelInfoLp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);        hotelInfoLp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);        hotelInfoLp.rightMargin = DeviceInfoUtil.getPixelFromDip(8);        hotelInfoLp.bottomMargin = DeviceInfoUtil.getPixelFromDip(95);        mHotelInfoLayout.setLayoutParams(hotelInfoLp);    }

这是横屏处理

我门知道 系统的videoView 控件 自带有播放,暂停 等进度条这是MediaContronller 当我们手点击的时候 进度条会显示,手离开界面的时候,会不显示,这是videoView 中的方法

 @Override    public boolean onTouchEvent(MotionEvent ev) {        if (isInPlaybackState() && mMediaController != null) {            toggleMediaControlsVisiblity();        }        return false;    }

再朝下看

private void toggleMediaControlsVisiblity() {        if (mMediaController.isShowing()) {            mMediaController.hide();        } else {            mMediaController.show();        }    }

最终调的是 mMediaController.hide(); 和 mMediaController.show(),

所以我门在自己的播放器界面要是实现自己的布局和播放器进度条 重写hide() 和 show() 方法即可

2 在视频播放的过程中经常会出现播放异常的情况,比如弹出无法播放视频的弹框,当然我门是不想让它弹的,于是我门的处理方式为:

 videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {            @Override            public boolean onError(MediaPlayer mp, int what, int extra) {                return true;            }        });

让onError 直接返回为true 这样能阻止异常框的弹出 同时什么都不做,原理是

   Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");                boolean error_was_handled = false;                if (mOnErrorListener != null) {                    error_was_handled = mOnErrorListener.onError(mMediaPlayer, msg.arg1, msg.arg2);                }                if (mOnCompletionListener != null && ! error_was_handled) {                    mOnCompletionListener.onCompletion(mMediaPlayer);                }                stayAwake(false);

这里error_was_handled 为true 这样就不走进mOnCompletionListener.onCompletion(mMediaPlayer);
了。

3 视频上线发现 在部分小米机型和魅族等机器上横屏 视频没有办法横屏。解决方案为

在布局中

 <RelativeLayout        android:id="@+id/videoView_layout"        android:layout_width="match_parent"        android:layout_height="match_parent">        <VideoView            android:id="@+id/video"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:visibility="gone" />    </RelativeLayout>

嵌套RelativeLayout;

在代码中处理

     RelativeLayout.LayoutParams layoutParams =                new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);        mVideoViewLayout.setLayoutParams(layoutParams);        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

4 在视频开发中,回发现window Leacked 问题,看了下
MediaController 的show 方法

    if (!mShowing && mAnchor != null) {            setProgress();            if (mPauseButton != null) {                mPauseButton.requestFocus();            }            disableUnsupportedButtons();            updateFloatingWindowLayout();            mWindowManager.addView(mDecor, mDecorLayoutParams);             mShowing = true;        }        updatePausePlay();

在不停的向view 中加布局,在MediaContrller 中方法了 中hide

  /**     * Remove the controller from the screen.     */    public void hide() {        if (mAnchor == null)            return;        if (mShowing) {            try {                mHandler.removeMessages(SHOW_PROGRESS);                mWindowManager.removeView(mDecor);            } catch (IllegalArgumentException ex) {                Log.w("MediaController", "already removed");            }            mShowing = false;        }    }

讲view remove 因此 我门在activity 的industry 的生命周期的回调中 执行 hide() 方法即可

0 0