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();
                }
            }
    }
相关推荐
千里马学框架5 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台5 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone5 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc5 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo5 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077005 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼5 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone5 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen5 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone5 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui