android 实现播放视频画中画功能遇到的问题点

画中画功能

Android 8.0 Oreo(API Level 26)允许活动启动画中画 Picture-in-picture(PIP)模式,我就是采用官方api模式实现,还有一种实现方案采用的是window方式,我项目里采用的是第三方播放器感觉用window方式实现困难了些不好衔接。

具体实现很简单就几点 就是参照的官方文档

1在你的manifest配置文件配置你的播放类acitvity

 <activity android:name="VideoActivity"
  android:supportsPictureInPicture="true"
  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
  android:launchMode="singleTask"

2在播放器控制栏添加的一个小窗播放按钮(参考爱奇艺) 点击按钮进入画中画模式

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        PictureInPictureParams.Builder pictureInPictureParamsBuilder = new PictureInPictureParams.Builder();
        mVideoWith = Player.getVideoWidth();
        mVideoHeight = Player.getVideoHeight();
        if (mVideoWith != 0 && mVideoHeight != 0) {
            Rational aspectRatio = new Rational(mVideoWith, mVideoHeight);
            pictureInPictureParamsBuilder.setAspectRatio(aspectRatio);
        }
        //进入pip
        enterPictureInPictureMode(mPictureInPictureParamsBuilder.build());
    }

3监听进入退出画中画

@Override
    public void onPictureInPictureModeChanged (boolean isInPictureInPictureMode, Configuration newConfig) {
        if (isInPictureInPictureMode) {
            // 进入画中画 这里隐藏全屏播放的ui
        } else {
            // 退出画中画 这里显示ui
        }
    }

    @Override
    public void onUserLeaveHint() {
	/ /当点击home键会触发这个方法,这里也可以调用进入画中画 看需求,我这里没有些写任何代码
    }

官方文档写的大概也是这些

总结下完成功能后遇到的几个问题

1 切换画中画 小屏会白一小会 才显示继续播放的视频我用的小米手机测试的,查看官方文档有写到

Android 12 对全屏窗口和画中画窗口之间的动画过渡效果进行了重大改进

从 Android 12 开始,PictureInPictureParams.Builder.setAutoEnterEnabled(true) 标志可提供更流畅的动画,用于在画中画模式下使用手势导航过渡到视频内容(例如,从全屏向上滑动到主屏幕时)。如果您的应用属于 ENTERTAINMENT、COMMUNICATION 或 VIDEO_PLAYER 应用类别,我们建议您采用此方式。

我是基于Android11做的没有setAutoEnterEnabled这个方法,但文档中还提供另一个方法

在 Android 8.0 中引入画中画功能时,sourceRectHint 用于指明在转换为画中画之后可见的 activity 区域,例如视频播放器中的视频视图边界。从 Android 12 开始,操作系统使用 sourceRectHint 在进入和退出画中画模式时实现更流畅的动画。

如果您的应用未提供适当的 sourceRectHint,画中画过渡仍正常运行,但动画不够精美

所以设置sourceRectHint 这个方法解决了这个问题

  Rect rect = new Rect();
  PlayerView.getGlobalVisibleRect(rect);
  pictureInPictureParamsBuilder.setSourceRectHint(rect);

2 切换画中画模式变成小屏后 页面会自动回到上一个页面,但是这个页面的布局会乱,页面控件变大了,一开始我以为是我引用的AndroidAutoSize 适配框架的原因 ,他们有冲突毕竟这个框架是全局适配的,后来发现不是 。

  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"

在切换画中画自动回到的上个页面activity也都配置上面属性,解决了这个问题

3 在画中画模式下操作别的功能 进入别的页面 有的页面直接在画中画小窗里打开了,这个是因为你打开的页面activity启动模式android:launchMode="singleTask" 把他去掉就好

4 在画中画模式下 在点击别的视频进入播放页面,由于我的播放页面是上面视频下tablyout+viewpager+fragment 根据不同需求 视频下面的fragment数量不一样 有的两个tab 有的三个,当三个进两个时java.lang.IllegalStateException:ViewPager: Can't Change Tag of Fragment出现这个异常,当两个进三个时下面fragment没有更新 ,我明明已经clear掉集合里的fragment了,原来是因为viewpager在加载当前页的时候已经将pager页左右页的内容加载进内存里了,并没有真正的删除,出现异常应该应该是一个位置有两个相同tag的fragment。

解决方案

将FragmentPagerAdapter 替换成FragmentStatePagerAdapter,因为前者只要加载过,fragment中的视图就一直在内存中,在这个过程中无论你怎么刷新,清除都是无用的,直至程序退出; 后者可实现真正删除。

重写Adapter的方法--getItemPosition(),让其返回PagerAdapter.POSITION_NONE

@Override
	public int getItemPosition(Object object) {
		return PagerAdapter.POSITION_NONE;
	}

进入新的播放页面会触发onNewIntent

 @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
		//获取视频url
		//重置viewpager fragment 等大概逻辑,如果视频是进入画中画模式之前的视频 这里可以不做任何处理
    }

5 点击画中画小屏的关闭按钮要关闭activity,这个点击关闭按钮会除非 播放类activity的 onStop方法 利用这个加个变量判断

   @Override
    protected void onStop() {
        super.onStop();
        closePip = true;
    }

   @Override
    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
        if(isInPictureInPictureMode){
          
            }else {
                if(closePip){
                    finish();
                }
            }
    }
相关推荐
problc23 分钟前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
帅得不敢出门11 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了12 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任14 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山14 小时前
Android“引用们”的底层原理
android·java
迃-幵15 小时前
力扣:225 用队列实现栈
android·javascript·leetcode
大风起兮云飞扬丶15 小时前
Android——从相机/相册获取图片
android
Rverdoser15 小时前
Android Studio 多工程公用module引用
android·ide·android studio
aaajj15 小时前
[Android]从FLAG_SECURE禁止截屏看surface
android
@OuYang16 小时前
android10 蓝牙(二)配对源码解析
android