学更好的别人,
做更好的自己。
——《微卡智享》
本文长度为1839字,预计阅读5分钟
前言
上一篇《Android画中画(PIP)模式使用》介绍了画中画的使用,今天这篇来讲讲Action按钮的使用,主要是广播方式更新UI及Android 12后的兼容性问题。
实现效果
代码实现
微卡智享
还是接着上一篇的程序代码,我们在这里进行处理,文章的最后会把Demo的源码地址发送上来。
定义广播和常量
ACTION_TEXTVIEW和ACTION_TOAST定义的是更新TextView的显示和使用Toast的两个常量,然后再定义一个BroadcastReceiver中写代码的实现,区分不同的action来实现更新TextView还是使用Toast弹窗。
private val ACTION_TEXTVIEW = "textview"
private val ACTION_TOAST = "toast"
private val ACTION_VALUE = "value"
//定义广播接收
private var mBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
val str = it.getStringExtra(ACTION_VALUE)
when (it.action) {
ACTION_TEXTVIEW -> {
binding.textView.text = str
}
ACTION_TOAST -> {
context?.let { mContext ->
Toast.makeText(mContext, str, Toast.LENGTH_SHORT)
.show()
}
}
else -> {
return@let
}
}
}
}
}
实现RemoteAction的发送广播
这个主要是由PendingIntent来实现的,当第一个按钮点击返回应用程序全屏时,用到的PendingIntent.getActivity,而第二和第三个按钮通过发送广播的方式就会用到了PendingIntent.getBroadcast,所以这里我们写了一个函数,通过函数的参数来生成对应的PendingIntent。
private fun getPendingIntent(intent: Intent, requestcode: Int, flag: Int = 1): PendingIntent {
when (flag) {
1 -> return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getActivity(
this, requestcode,
intent,
PendingIntent.FLAG_IMMUTABLE
)
} else {
PendingIntent.getActivity(
this, requestcode,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
else -> return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
this, requestcode,
intent,
PendingIntent.FLAG_IMMUTABLE
)
} else {
PendingIntent.getBroadcast(
this, requestcode,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
}
}
重点:
函数里面加入了判断Android的SDK版本,是因为上一篇中没加入这个,8.0的模拟器中运行正常,但是真机Android 12就会直接崩溃了,原因是Android 12 声明特定 PendingIntent 对象是否可变,请分别使用 PendingIntent.FLAG_MUTABLE 或 PendingIntent.FLAG_IMMUTABLE 标志。如果您的应用试图在不设置任何可变标志的情况下创建 PendingIntent 对象,系统会抛出 IllegalArgumentException。
重新再修改enterPipModel函数,加入创建三个按钮的代码。
private fun enterPipModel() {
val builder = PictureInPictureParams.Builder()
//设置Actions
val actions = arrayListOf<RemoteAction>()
//1.返回全屏窗口
val pIntent1 = getPendingIntent(intent, 1)
val remoteAction1 = RemoteAction(
Icon.createWithResource(
this,
R.mipmap.ic_phone_round
), "画中画", "Vaccae", pIntent1
)
actions.add(remoteAction1)
//2.修改Text显示
val intent2 = Intent(ACTION_TEXTVIEW).putExtra(ACTION_VALUE, "Vaccae点击了Text Action")
val pIntent2 = getPendingIntent(intent2, 2, 2)
actions.add(
RemoteAction(
Icon.createWithResource(
this,
R.mipmap.ic_launcher
), "TextView", "Vaccae", pIntent2
)
)
//3.实现Toast控制
val intent3 = Intent(ACTION_TOAST).putExtra(ACTION_VALUE, "关注微卡智享")
val pIntent3 = getPendingIntent(intent3, 3, 2)
actions.add(
RemoteAction(
Icon.createWithResource(
this,
R.mipmap.ic_launcher
), "Toast", "Vaccae", pIntent3
)
)
builder.setActions(actions)
//设置宽高比例,第一个是分子,第二个是分母,指定宽高比,必须在 2.39:1或1:2.39 之间,否则会抛出IllegalArgumentException异常。
val rational = Rational(5, 11)
builder.setAspectRatio(rational)
//Android12下加入的画中画配置,对于非视频内容停用无缝大小调整
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setSeamlessResizeEnabled(false)
builder.setAutoEnterEnabled(true)
}
enterPictureInPictureMode(builder.build())
}
判断画中画模式进入和退出时的广播监听
上一篇中使用onPictureInPictureModeChanged函数来判断时入画中画模式后将button按钮隐藏,回到全屏模式后再显示出来,现在在这个函数中再加入进入画中画时注册广播接收,关闭画中画时就释放广播接收,代码如下:
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration?
) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
if (isInPictureInPictureMode) {
binding.textView.text = "画中画模式"
binding.btnpip.visibility = View.GONE
//进入画中画时注册广播接收
val intentFilter = IntentFilter()
intentFilter.addAction(ACTION_TEXTVIEW)
intentFilter.addAction(ACTION_TOAST)
registerReceiver(mBroadcastReceiver, intentFilter)
} else {
binding.textView.text = "正常模式"
binding.btnpip.visibility = View.VISIBLE
//退出画中画时停止广播接收
unregisterReceiver(mBroadcastReceiver)
}
}
有时候当用户主动按主屏幕键或是最近的应用按钮,还是可以切换到画中画模式,这里就用到了onUserLeaveHint方法了。
完成上面的步骤,画中画的按钮功能实现的Demo就完成了。
微卡智享
源码地址
https://github.com/Vaccae/AndroidPipDemo.git
点击阅读原文可以看到“码云”的代码地址
完
往期精彩回顾