Android

您所在的位置:网站首页 平板画中画模式 Android

Android

2024-05-22 22:44| 来源: 网络整理| 查看: 265

3.1 启动launchMode=“singleTask”的Activity会在画中画窗口中打开

问题 下面这个视频中:我们在主页面(下面简称:MainActivity)中,先打开一个画中画页面(下面简称:PipActivity),再打开一个launchMode=singleTask页面(下面简称:SingleTaskActivity)。奇怪的事情发生了,SingleTaskActivity居然展示在PipActivity中。

image description

官方的demo下也有人提了这个issue,现在还是open状态。

原因分析 我们先通过扔物线老师的这个视频 ,回顾下Activity的四种启动方式、Task、taskAffinity等概念。有了相关的基础知识后,再思考背后的原因。

从上面的奇怪表现看来,我一开始想到的是:PipActivity与MainActivity似乎处于不同的Task。于是尝试打印相关的Task信息。

打开PipActivity后的Task信息。

截屏2023-09-10 15.45.31.png 果然两个Activity处于不同的Task中。

在上一步的基础上,再打开SingleTaskActivity。

截屏2023-09-10 15.45.42.png 可以看到SingleTaskActivity与PipActivity处于同一个Task中。

上面的信息解释了SingleTaskActivity为啥会出现在PipActivity窗口中了,因为两者处于同一个Task中。

为啥会出现在同一个Task中呢?常规的standard、singleTop启动时,是直接在当前Task中创建,而singleTask的Activity在启动时会查找taskAffinity相同的Task,刚好这时候应用有两个taskAffinity=11033:com.example.test的Task并且PipActivity所在的Task是最新的,所以启动SingleTaskActivity时就被添加到PipActivity所在的Task了。(以上是个人猜测)

解决 那么如果我们让PipActivity独占一个Task,那么SingleTaskActivity就不会出现在PipActivity窗口中了。

有了大致方向,我首先想到的是:让PipActivity以singleInstance的方式启动。

image description

这样设置后,SingleTaskActivity能正常启动了,但是打开PipActivity时会有转场动画,比较影响体验。

于是换另外一个思路: PipActivity以默认的方式启动,但给它设置一个单独的taskAffinity。

output.gif

搞定,这样设置后,能满足我们的需求。

设置了单独的taskAffinity会导致任务列表中有两个相同应用的任务,可以设置下面两个参数android:excludeFromRecents="true"和android:autoRemoveFromRecents="true"来保证只有一个。

3.2 无法区分画中画窗口的“最大化”和“关闭”按钮

image description

问题 上图是画中画窗口,红色框框是两个系统自带的按钮:“最大化”按钮和“关闭”按钮。这两个按钮的作用不同,代表的用户目的不一样,需要区分处理。

解决 但可惜系统没有提供区分的方法,不过在stackoverflow上看到一个有意思的解决办法:

@Override public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) { if (!isInPictureInPictureMode) { if (getLifecycle().getCurrentState() == Lifecycle.State.CREATED) { // 用户点击“关闭”按钮 } else if (getLifecycle().getCurrentState() == Lifecycle.State.STARTED){ // 用户点击”最大化“按钮 } } }

点击“最大化”按钮或“关闭“按钮时,页面都会退出画中画并回调onPictureInPictureModeChanged方法,但回调时页面的生命周期不一样,可以利用这点来进行判断。自己也验证了一下,上面的代码是没有问题的。

3.3 自定义画中画按钮

image description

画中画窗口最下面这行是自定义按钮区域,我们可以自定义想要的功能。

定义操作按钮 private val mPlayAction get() = RemoteAction( Icon.createWithResource(this, R.drawable.edu_ic_play_video), "", "", PendingIntent.getBroadcast( this, REQUEST_CODE_PLAY, Intent(ACTION_PLAY), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) ) 注意:每个RemoteAction的REQUEST_CODE(比如上面的REQUEST_CODE_PLAY)都应该不一样。 设置操作按钮 可以通过Activity的enterPictureInPictureMode和setPictureInPictureParams进行设置。 监听并响应操作 上面通过PendingIntent.getBroadcast给按钮设置了一个PendingIntent,当按钮被点击时就会触发对应的广播,我们只要监听广播就行了。 // 定义广播接收器 private val mediaActionReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { when (intent?.action) { ACTION_PLAY -> { // 执行播放操作 } } } } // 注册广播接收器 context.registerReceiver(mediaActionReceiver, IntentFilter().apply { addAction(ACTION_PLAY) }) 注意:在不需要的时候,记得通过context.unregisterReceiver取消监听。

3.4 开启画中画前的检查

能否开启画中画,受系统版本、画中画权限、系统可运行内存大小等影响,在进入画中画前需要挨个检查。

fun checkOpenPipMode(context: Context): Boolean { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // Android O以下不支持画中画 return false } val appOpsManager = context.getSystemService(APP_OPS_SERVICE) as AppOpsManager if (AppOpsManager.MODE_ALLOWED != appOpsManager.checkOpNoThrow( AppOpsManager.OPSTR_PICTURE_IN_PICTURE, context.applicationInfo.uid, context.packageName ) ) { // 没有画中画权限 ActivityUtils.startActivity( Intent("android.settings.PICTURE_IN_PICTURE_SETTINGS").apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK } ) return false } if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) { // 低 RAM 设备可能无法使用画中画模式 return false } return true }

3.5 开启画中画时,平板的dp发生变化

private fun calculateDp() { val density = application.resources.displayMetrics.density val screenWidth = application.resources.displayMetrics.widthPixels val dp = screenWidth / density println("Test_pip screenWidth=$screenWidth density=$density dp=$dp") }

上面这段代码涉及的density和dp是常见屏幕适配方案的关键参数,对页面布局有较大影响。

问题 开发过程中遇到一个情况,平板上打开画中画页面后,此时全局的application.resources.displayMetrics.widthPixels变成以画中画小窗口为依据,导致screenWidth变小,从而导致dp变小,从而导致相关适配的判断出现问题。

上述情况从画中画页面打开,持续到下一个非画中画页面打开,只在部分平板出现,暂时没有找到原因。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3