行为变更 | Android 12 中不受信任的触摸事件

谷歌开发者 / 2021-08-20 11:47:03

图片
我们在 Android 12 中进行了一些变更,来提升应用和平台的安全性,进而使我们的用户能够拥有更安全的使用体验。回顾关于隐私和安全的文章,请参阅: 政策更新 | 开发者如何处理软件包可见性。

触摸控制是 Android 系统中同应用进行交互的主要方式。Android 12 中采取了额外的措施,来确保触摸事件被正确地传递给了应该响应此事件的应用,以此确保触摸交互的直观和安全性。具体地说,就是在 Android 12 中,如果触摸事件是从一个不同的应用窗口传递的,那么此事件会被屏蔽。这一改变将影响所有在 Android 12 中运行的应用,且与应用的 "targetSdkVersion" 无关。这有助于帮助用户更直观地确认他们正在进行交互的应用。继续阅读本文来看看您的应用是否会受到此变更的影响,以及了解如何针对此变更测试您的应用。





尽可能使用特殊用途 (Special-Purpose) 的 API


在检查您的应用是否会受此影响之前,最好先评估一下您应用的某些场景是否可以使用以下 Android API。这些 API 部分由系统控制,可以被信任,因此您不需要担心使用这些 API 会受到限制。它们是:

Bubbles: Bubbles 是像气泡一样浮动在其他应用内容的上层,并且会跟随用户所处的位置,还可以展开以显示应用功能和信息。

Picture-in-Picture (PIP): PIP 功能允许应用在一个小窗口中显示内容,用户可以通过固定到屏幕一角的小窗口观看视频,同时在应用之间进行导航或浏览主屏幕上的内容。用户还可以拖动 PIP 窗口,并可以点击它来展开或进行关闭。

Notifications: 通知是指 Android 在您应用的界面之外显示的消息,旨在向用户提供提醒、来自他人的通信信息或您应用中的其他适时弹出的信息。用户可以点按通知来打开应用,或直接在通知中执行操作。

Snackbars 和 Toasts: 如果您需要在应用中显示一条简短的信息,可以使用 Snackbars。如果您需要应用在后台的情况下显示信息,可以看看 Toasts 是否符合您的需求。


Bubbles
https://developer.android.google.cn/guide/topics/ui/bubbles
Picture-in-Picture
https://developer.android.google.cn/guide/topics/ui/picture-in-picture
Notifications
https://developer.android.google.cn/guide/topics/ui/notifiers/notifications
Snackbars
https://developer.android.google.cn/reference/com/google/android/material/snackbar/Snackbar
Toasts
https://developer.android.google.cn/guide/topics/ui/notifiers/toasts

如果您应用的使用场景匹配了上述某个 API 的使用场景,那么强烈建议您使用这些 API。不仅仅是因为这些 API 简单易用,它们还更加安全,而且用户已经对它们中的大多数很熟悉了。




我会受到影响吗?


如果您的应用不能使用上述 API,而是让触摸事件直接通过其窗口传递,那么在 Android 12 中它们可能无法按预期传递到下层。这方面的例子包括但不仅限于以下示例:
使用 FLAG_NOT_TOUCHABLE 标志的 TYPE_APPLICATION_OVERLAY 窗口。
使用 FLAG_NOT_TOUCHABLE 标志的 Activity 窗口。

FLAG_NOT_TOUCHABLE
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams#FLAG_NOT_TOUCHABLE

TYPE_APPLICATION_OVERLAY
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams?hl=zh-TW#TYPE_APPLICATION_OVERLAY


如果您正在使用 FLAG_NOT_TOUCHABLE,那么您的应用可能会被影响,除非您的应用符合以下某个豁免条件:
应用中的交互。只有当用户与您的应用进行互动时才会显示叠加层。

可信窗口。这些窗口包括但不仅限于: 无障碍窗口、输入法 (IME) 窗口和 Google 助理窗口。

不可见窗口。窗口根视图是 GONE 或 INVISIBLE。

全透明窗口。窗口的 alpha 属性值为 0.0。

足够半透明的系统警报窗口。该窗口是 TYPE_APPLICATION_OVERLAY 类型的,并且其 alpha 值等于或小于 InputManager.getMaximumObscuringOpacityForTouch() 的值。这个值目前在开发者预览 3 的版本中是 0.8,但在最终版发布之前可能会改变。如果有多个这种类型的重叠窗口,则会使用它们各自的 opacity 值合并计算出一个值作为最终的结果。



无障碍窗口
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams?hl=zh-TW#TYPE_ACCESSIBILITY_OVERLAY
输入法 (IME) 窗口
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams?hl=zh-TW#TYPE_INPUT_METHOD
Google 助理窗口
https://developer.android.google.cn/reference/android/service/voice/VoiceInteractionSession
GONE
https://developer.android.google.cn/reference/android/view/View#GONE
INVISIBLE
https://developer.android.google.cn/reference/android/view/View#INVISIBLE
alpha
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams#alpha
InputManager.getMaximumObscuringOpacityForTouch()
https://developer.android.google.cn/reference/android/hardware/input/InputManager#getMaximumObscuringOpacityForTouch()
合并计算出一个值
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams#combined-obscuring-opacity

如果您的使用场景并不包含于上述列表内,那么触摸事件将会被屏蔽。否则的话,如果您想阻止触摸事件传递,可以考虑删除 FLAG_NOT_TOUCHABLE 标志,而如果想让触摸事件穿透下去,可以调整您的代码来符合上述的几种情况之一。接下来我们会介绍必须要改变的一些常见模式的例子。




有着透明背景且无 UI 元素的窗口


在有着透明背景的窗口中展示某些 UI 的应用,可以在适当的时候在视图层面隐藏它们的 UI,同时添加 FLAG_NOT_TOUCHABLE 标志,这样用户就可以与下层的内容进行交互了。

图片

如果像上图一样,应用仅仅是隐藏了 UI,要么是通过删除子视图的方法隐藏,或是改变它们的可见性 (visibility) 并添加 FLAG_NOT_TOUCHABLE 标志来允许用户与下层的视图进行交互,因为对下层其他应用的触摸事件会被屏蔽,所以这样的方法在 Android 12 上就不再起作用了 (注意与前面提到的豁免条件的区别,在这里我们改变的是内部视图,而不是窗口)。在这种情况下想解决此类问题,您可以:
使用 WindowManager.removeView() 来移除窗口,并传递给根视图。

通过在根视图上调用 View.setVisibility(),使用 View.GONE 或 View.INVISIBLE 让窗口不可见。

通过 LayoutParams.alpha 让窗口的 opacity 值为 0.0。


WindowManager.removeView()
https://developer.android.google.cn/reference/android/view/ViewManager#removeView(android.view.View)

View.setVisibility()
https://developer.android.google.cn/reference/android/view/View#setVisibility(int)

View.GONE
https://developer.android.google.cn/reference/android/view/View#GONE

View.INVISIBLE
https://developer.android.google.cn/reference/android/view/View#INVISIBLE

LayoutParams.alpha
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams#alpha



每当您需要再次显示那个界面时,您只需要把上面的动作反过来设置即可。




不必要的大窗口


有时应用会想要显示一些小的 UI 界面,并同时允许用户同窗口下层的内容进行交互。在之前,应用可以通过简单地使用一个全屏窗口,并将其标记为 FLAG_NOT_TOUCHABLE 来实现,如图 1 所示:

图片

请注意,在以前的操作系统版本中,通过实际的 UI 元素进行的触摸事件,在这种情况下会传递到下层的窗口中。在这种情况下,首先请查看一下 Toast API 是否能满足需求,不行的话,解决方案也很简单——在右侧的图片有说明: 您只需要将窗口的边界缩小到实际的 UI 大小,并使用 FLAG_NOT_TOUCH_MODAL,有时您也可能需要删除 FLAG_NOT_TOUCHABLE。



Toast
https://developer.android.google.cn/guide/topics/ui/notifiers/toasts

FLAG_NOT_TOUCH_MODAL
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams#FLAG_NOT_TOUCH_MODAL


这样,在您的 UI 外的触摸事件,将直接穿透到下层的窗口,不再被屏蔽。





半透明窗口


如果您使用了一个 TYPE_APPLICATION_OVERLAY 窗口,并需要在显示内容时允许触摸事件穿透下去,那您就必须降低窗口的不透明度,让用户能够合理地看到他们在窗口后所触摸的 UI 元素。

图片

您必须在窗口级别上降低不透明度,仅仅改变视图的不透明度是不行的。您可以使用 LayoutParams.alpha 来降低不透明度,使其低于或者等于
InputManager.getMaximumObscuringOpacityForTouch() 的值,如右边的图片所示。这个值目前是 0.8,但是在 Android 12 最终版本发布前可能会改变。

现在,只要您应用内的多个窗口没有相互重叠,触摸事件就会穿透到下层的窗口。关于重叠窗口的更多细节,请查阅 FLAG_NOT_TOUCHABLE 文档。


LayoutParams.alpha
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams#alpha

InputManager.getMaximumObscuringOpacityForTouch()
https://developer.android.google.cn/reference/android/hardware/input/InputManager#getMaximumObscuringOpacityForTouch()

FLAG_NOT_TOUCHABLE
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams#FLAG_NOT_TOUCHABLE




无障碍服务



当使用 AccessibilityService (无障碍服务) 时,它可以创建 TYPE_ACCESSIBILITY_OVERLAY 类型的窗口,这些窗口是可信任的,因此可以免于前面所描述的一些限制。您只需要结合 AccessibilityService 的上下文,通过 getSystemService() 方法获得一个 WindowManager 来创建上述窗口。


TYPE_ACCESSIBILITY_OVERLAY
https://developer.android.google.cn/reference/android/view/WindowManager.LayoutParams#TYPE_ACCESSIBILITY_OVERLAY

AccessibilityService
https://developer.android.google.cn/reference/android/accessibilityservice/AccessibilityService

WindowManager
https://developer.android.google.cn/reference/android/view/WindowManager





如何测试您的应用是否受到影响



如果系统屏蔽了触摸操作,Logcat 会输出以下信息:

Untrusted touch due to occlusion by PACKAGE_NAME.


Logcat
https://developer.android.google.cn/studio/command-line/logcat?hl=zh-TW




接下来


如果您想了解到更多关于不受信任的触摸事件以及它们的例外情况,请查阅相关文档:



不受信任的触摸事件

https://developer.android.google.cn/about/versions/12/behavior-changes-all?hl=zh-TW#untrusted-touch-events

例外情况
https://developer.android.google.cn/about/versions/12/behavior-changes-all?hl=zh-TW#untrusted-touch-events-exceptions



图片

推荐阅读


图片 点击屏末 | 阅读原文 | 查看 Android 12 上运行的所有应用都会受到影响的行为变更



图片

图片

图片

阅读原文
阅读 3031

写下你的留言


----------------------------
本文由新墨整理并发布。转载来自互联网,若侵权则删除!
新墨5年开发经验,45名团队成员,上线已达100+产品,于北京和成都2个城市提供技术开发服务。致力于提供APP开发,小程序开发,微信开发,IOT物联网开发,电商系统开发,教育系统开发,H5开发,游戏开发,用户体验设计,课件设计

新墨官网地址:http://www.sinmore.com.cn/
新墨物联网站:http://www.sinmore.cn/
布鸽科技:http://www.buge.vip/

热门文章
最新文章
推荐文章