MediaPlayer+TextureView全屏播放视频

项目需要做一个简单的播放视频功能demo,考虑到需求较简单(实现不超过2min的MP4格式短视频播放),所以就没考虑使用复杂的第三方视频库了。最初敲定使用系统原生的VideoView实现,后来发现不能在列表中使用普通的VideoView 。VideoView 继承自SurfaceView,而SurfaceView并没有UI同步缓冲区。这就导致了在列表滚动的时候,正在播放的视频可能无法跟上滚动的步伐。针对这个问题继续查资料,最终选择使用MediaPlayer+TextureView实现视频播放。相关的资料很多,这里就不细说了。我主要说一下实现全屏播放的实现思路及遇到的问题。

一、在activity中留一个全屏的ViewGroup放置播放器实现全屏

在相应Activity中预留一个放置播放器的宽高都是match_parent的ViewGroup,大小切换就是把播放器添加到本来的小容器和添加到全屏的ViewGroup中来回切换。

全屏时,把从当前视图移除的播放器View即自定义的TextureView重新添加到预留的ViewGroup中,并且设置activity为横屏。

在activity中监听屏幕状态变化:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
    	TestLog.d(TAG, "onConfigurationChanged : fullScreen=" + fullScreen);
    	super.onConfigurationChanged(newConfig);
    	if (fullScreen != null && newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE && getVideoContent() != null) {
    		getVideoContent().setClickable(true);//拦截点击事件
    		ViewUtils.setVisible(getVideoContent(), View.VISIBLE);
    		fullScreen.full();
    		fullScreen = null;
    	} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
    		ViewUtils.setVisible(getVideoContent(), View.GONE);
    	}
    }

相应的实现点击全屏按钮实现全屏逻辑:

     public void clickESC() {
					PingbackUtils_3_9_0.pingVideoFullScreen();
					if (mAdapter != null) {
						final Context context = mAdapter.getContext();
						if (context instanceof BaseActivity) {
							((BaseActivity) context).setFullScreen(new IFullScreen() {
								
								@Override
								public void full() {
									handler.addVideo((ViewGroup) ((BaseActivity) context).getRootView(), false);
									TestLog.d(TAG,
											TestLog.isDebug() ? "clickESC videoInfo.getCurrentPosition()=" + videoInfo.getCurrentPosition() : "");
									//handler.seekTo(videoInfo.getCurrentPosition());
									handler.fullScreen((BaseActivity) context);//这个要放到addVideo后面,需要是否全屏的状态
								}
							});
							
							SingleVideoHandler.setOrientation((BaseActivity) context);
						}
					}
				}

退出全屏倒着做就好了,设置会竖屏,将 播放器view ViewGroup 中移除,重新添加到当前视图。


注意:切换横竖屏时为了避免Activity重新走生命周期,需要在Manifest.xmlactivity标签下添加如下配置:

     android:configChanges="orientation|keyboardHidden|screenSize"

到了这里别以为已经万事大吉了,亲自实践发现小屏播放和切换大屏衔接的不好,会出现短暂的黑屏现象。这是因为切换到大屏

时视频view从当前播放视图移除重新添加到大屏视图后,TextureView会重绘,就会重新new一个surfaceTexture,并重新回调onSurfaceTextureAvailable()

方法,这样TextureView的数据通道SurfaceTexture发生了变化,但是mediaPlayer还是持有原来的SurfaceTexture。

解决方法:重写onSurfaceTextureAvailable()、onSurfaceTextureDestroyed(),在从当前视图移除播放器viwe之前保存当前SurfaceTexture,

重新添加到大屏视图时,将之前保存的SurfaceTexture重新设置给当前播放器view。

	@Override
        public void onSurfaceTextureAvailable(final SurfaceTexture surface, final int width, final int height) {
        	TestLog.d(TAG, TestLog.isDebug() ? "onSurfaceTextureAvailable:surface=" + surface : "");
        	TestLog.d(TAG, TestLog.isDebug() ? "onSurfaceTextureAvailable:mSurfaceTexture=" + mSurfaceTexture : "");
        	if (Utils.hasJellyBeanMR2()) {//如下方法在android4.2会崩溃,所以4.3之后(包括4.3)再使用
	        	if (mSurfaceTexture == null) {
	                mSurfaceTexture = surface;  
	                TestLog.d(TAG, TestLog.isDebug() ? "after set:mSurfaceTexture=" + mSurfaceTexture : "");
	                openVideo();
	            } else {
	            	setSurfaceTexture(mSurfaceTexture);
	            }
        	} else {
        		mSurface = new Surface(surface);
                openVideo();
        	}
        }

        @Override
        public boolean onSurfaceTextureDestroyed(final SurfaceTexture surface) {
        	TestLog.d(TAG, TestLog.isDebug() ? "onSurfaceTextureDestroyed:surface=" + surface : "");
            // after we return from this we can't use the surface any more
            /*if (mSurface != null) {
                mSurface.release();
                mSurface = null;
            }
            if (mMediaController != null) mMediaController.hide();
            release(true);
            return true;*/
        	return mSurfaceTexture == null;
        }

参考

VideoView and TextureVideoView on Android

Android视频播放器实现小窗口和全屏状态切换

[Android基础] VideoView





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好,关于使用MediaPlayer和SurfaceView播放视频,可以按照以下步骤进行: 1. 在XML布局文件中添加SurfaceView控件: ``` <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. 在Java代码中获取SurfaceView控件,创建MediaPlayer对象,并设置相关监听器: ``` // 获取SurfaceView控件 SurfaceView surfaceView = findViewById(R.id.surface_view); // 创建MediaPlayer对象 MediaPlayer mediaPlayer = new MediaPlayer(); // 设置SurfaceView作为MediaPlayer的显示界面 mediaPlayer.setDisplay(surfaceView.getHolder()); // 设置MediaPlayer的一些监听器 mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // 视频准备完成后自动播放 mp.start(); } }); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { // 视频播放完成后的处理 } }); mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { // MediaPlayer出错时的处理 return false; } }); ``` 3. 设置MediaPlayer的数据源、准备视频等操作: ``` try { // 设置MediaPlayer的数据源 mediaPlayer.setDataSource("video_path"); // 准备视频 mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } ``` 4. 在需要的地方控制视频的播放、暂停、停止操作: ``` // 播放视频 mediaPlayer.start(); // 暂停视频 mediaPlayer.pause(); // 停止视频 mediaPlayer.stop(); ``` 希望以上步骤能帮到您。若有疑问,请随时咨询。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值