前言
最近在做一个需求的时候发现,在Android 7.0上面,想要唤出系统的最近任务界面,只能通过辅助功能才能实现,Stack Overflow上有这个问题的讨论:How do I launch the recent apps menu in android?
原本想要看看辅助功能是如何唤出系统的最近任务界面的,但是搜了一下AccessibilityService,几乎大部分的文章都是介绍如何利用辅助点击实现抢红包的功能,很少有提到我想搞清楚的事情:Accessibility事件具体是如何分发的。于是,趁着这个机会翻看Android 7.0的源码,整理了Accessibility事件分发流程。
Accessibility事件分发流程简述
先用一张流程图,简要描述Accessibility事件的分发流程:
Accessibility事件分发流程图Accessibility事件经过目标App端的AccessibilityManager,分发给远程的AccssibilityManagerService,最后分发给辅助App端AccessibilityService。
说明
目标App是指发出Accessibility事件的App,而辅助App是指想要接收Accessibility事件进行一些辅助操作的App。以抢红包插件为例,微信是目标App,发出Accessibility事件,而抢红包插件就是辅助App,接收Accessibility事件。
本篇文章介绍的是辅助App接收到目标App发出的Accessibility事件过程,以后有机会再分析,辅助App端向目标App发送如点击事件等功能的过程。
以下几个类会在文中经常出现,先在这里露个脸:
AccessibilityManager,目标App借助AccessibilityManager来向远程的AccssibilityManagerService发送Accessibility事件
AccssibilityManagerService,远程的AccssibilityManagerService负责将目标App的Accessibility事件分发给辅助App
AccssibilityService,l辅助App通过AccessibilityService接收Accessibility事件
为了方便阅读,下文对以上几个类使用简称:
AccessibilityManager: AM
AccssibilityService: AS
AccssibilityManagerService: AMS
下面,我们跟着源码,看看Accessibility事件的具体分发流程。
一. 目标App与远程AMS建立联系
AMS是运行在系统进程的,目标App想要跟AMS进行跨进程通信,目标App就一定得先跟远程的AMS建立联系,也就是需要获取到远程AMS的本地binder。所以我们先了解一下,目标App进程与远程AMS建立联系的过程。
1.1 目标App的AM向远程AMS端的通讯
目标App拥有AM的一个单例,AM在构造的时候,通过tryConnectToServicesLocked()方法,获取AMS的本地binder。
我们看看AM的静态getInstance方法:
目标App与远程AMS建立联系二. Accessibility事件从目标App分发到辅助App的过程
2.1 View把进行Accessibility事件分发给AM
View在触发一些如点击或者滑动的操作时,会调用sendAccessibilityEvent进行Accessibility事件的分发。
View把Accessibility事件分发到AccessibilityManager2.2 AM把Accessibility事件分发给远程AMS
下面看看AM的sendAccessibilityEvent方法
Accessibility事件从View分发到远程AccessibilityManagerService2.3 远程的AMS把Accessibility事件分发到辅助App的AS中
下面看看AMS的sendAccessibilityEvent方法:
AccessibilityManagerService把Accessibility事件分发到辅助App的AccessibilityService三. 辅助App端的AS与远程AMS的联系
3.1远程的 AMS与辅助App的AS建立联系的过程
上面说到,IAccessibilityServiceClient类型listener的onAccessibilityEvent(event),最终就会回调到AS的onAccessibilityEvent(event),那AMS具体是如何跟AS联系起来的呢?
IAccessibilityServiceClient.Stub的实现类IAccessibilityServiceClientWrapper,这个binder会在AS的onBind(Intent intent)返回,也就是绑定AS的时候,AS会返回IAccessibilityServiceClient类型的binder给AMS,这样远程的AMS就可以利用本地binder向AS进行通信,把Accessibility事件分发到辅助App的AS中了。
看看AS的onBind(Intent intent):
Accessibility事件的分发流程图
网友评论