抖音无障碍背景
国家近期开展了无障碍建设活动。为了积极响应国家号召,为抖音视障用户能够得到更好的交互体验,对抖音无障碍功能进行了专项治理和改造。
无障碍模式下的使用方法
抖音的无障碍功能实现主要是通过开启 Google TalkBack(或第三方屏幕阅读)功能,将用户在屏幕上触摸选中区域的内容朗读出来,使得视障人士可以根据朗读的内容获取自己当前操作区域的信息,从而提升视障人士的使用和交互体验。
常用的操作手势:
浏览某个 View:单击
点击某个 View:双击
沿某个方向滑动:双指沿所需方向滑动
顺序浏览页面:单指左右滑动
本文的目的
使研发同学对无障碍功能有一个更加全面的认识和了解,方便研发同学进行无障碍功能的开发。
本文将分为无障碍功能实现原理和无障碍功能实现实例两部分进行介绍。
无障碍功能实现原理
系统结构
无障碍功能的实现需要以下三个部分的支持:辅助 App(例如 TalkBack)、被辅助 app(用户使用的 app,例如抖音头条等)以及系统服务 AccessibilityManagerService,这三者之间的关系如下图所示:

从上图中可以看出,以上的流程主要涉及到三个进程的通信。辅助 app 和被辅助 app 不需要直接跟被辅助的 app 通信,而是通过 SystemServer 进行中转通信,这个过程主要涉及到了四个 aidl 接口:
被辅助 app->SystemServer(IAccessibilityManager.aidl)
当被辅助 app 产生触摸事件后,会通过该接口发送无障碍事件给 SystemServer 进程的 AccessibilityManagerService。
SystemServer->辅助 app(IAccessibilityServiceClient.aidl)
当 SystemServer 接收到被辅助 app 发送的无障碍事件时,会将事件通过该接口传递给辅助 app(例如 TalkBack)进行处理。
辅助 app->SystemServer(IAccessibilityServiceConnection.aidl)
SystemServer->被辅助 app(IAccessibilityInteractionConnection.aidl)
当需要被辅助 app 的某个 View 的信息时,可以通过这两个接口的 findAccessibilityNodeInfosByViewId 方法实现。
无障碍事件传递流程
当用户触摸屏幕时,会经过以下的流程将触摸事件传递给被触摸的 View:

下面本文将主要分析以上流程中四个重点部分的内容:无障碍模式下的事件转换、触摸事件到 Activity 的传递过程、事件传递给具体的 View 的分发过程以及最终无障碍事件的执行流程。
1.无障碍模式下的事件转换
在 TalkBack 开启的状态下,由于 TalkBack 的无障碍服务中声明了 android:canRequestTouchExplorationMode=''true'' ,因此开启 TalkBack 后 AccessibilityManagerService 会更新 AccessibilityInputFilter 的FLAG_FEATURE_TOUCH_EXPLORATION
(触摸浏览)属性置为 true。

在 FLAG_FEATURE_TOUCH_EXPLORATION 模式下会创建一个 TouchExplorer 对象。AccessibilityInputFilter 继承了 InputFilter,对输入事件进行过滤,通过和 TouchExplorer 共同实现 TalkBack 模式下的触摸浏览手势。TouchExplorer 负责将普通触摸事件转换为触摸浏览手势,例如将 MotionEvent.ACTION_DOWN