当前位置: 首页 > news >正文

Android 16系统源码_无障碍辅助(一)认识无障碍服务

前言

Android 的无障碍辅助功能(Accessibility)是一套专为残障用户或特殊场景设计的核心技术框架,旨在让所有用户都能便捷地操作设备。其功能覆盖视觉、听觉、运动能力和认知障碍支持,同时为开发者提供标准化 API 以实现应用适配。

核心功能组件

Android 提供了多种内置无障碍工具和服务,涵盖不同场景需求:

功能名称主要用途适用人群
TalkBack屏幕阅读器,通过语音和振动反馈界面内容视障用户
Voice Access语音控制界面元素(可见即可说)运动障碍/免提操作
Switch Access通过物理开关或摄像头动作控制设备重度运动障碍用户
Select to Speak点按或圈选文本后朗读内容阅读障碍/学习困难用户
字幕和音频增强实时字幕、声音放大器、左右声道平衡听障用户
高对比度模式调整界面颜色和字体大小以提升可读性低视力用户

技术架构与原理

Android 无障碍功能的实现依赖多层系统服务协作。

事件传递机制

  • 事件源:用户操作(如点击)或系统事件(如通知)触发 AccessibilityEvent。
  • 收集与分发:系统级服务 AccessibilityManagerService 统一管理事件,按类型分发给注册的无障碍服务。
  • 处理响应:开发者实现的 AccessibilityService 通过 onAccessibilityEvent() 接收事件并执行逻辑(如点击按钮、读取文本)。

界面元素访问

  • 控件树解析:通过 AccessibilityNodeInfo 获取界面元素的层级结构、属性(如文本、坐标)。
  • 窗口快照:AccessibilityWindowManager 维护窗口状态,提供跨应用的界面内容访问(需用户授权)。

语音与交互

  • 语音合成(TTS):TalkBack 使用 TextToSpeech 引擎朗读文本。
  • 手势映射:自定义手势(如双指滑动)触发操作,由 AccessibilityGestureDetector 解析。

简单案例

下面我们将会编写一个简单的案例,具体认识一下 Android 无障碍服务 (AccessibilityService) 。此案例主要用于获取当前屏幕上的所有文本信息。

步骤 1:添加无障碍服务声明(AndroidManifest.xml )

<serviceandroid:name=".MyAccessibilityService"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"android:exported="true"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService" /></intent-filter><meta-dataandroid:name="android.accessibilityservice"android:resource="@xml/accessibility_service_config" />
</service>

步骤 2:创建无障碍服务配置文件(res/xml/accessibility_service_config.xml)

<accessibility-servicexmlns:android="http://schemas.android.com/apk/res/android"android:description="@string/accessibility_service_desc"android:accessibilityEventTypes="typeWindowContentChanged|typeWindowStateChanged"android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows"android:canRetrieveWindowContent="true"android:settingsActivity="com.example.MainActivity"/>

步骤 3:实现无障碍服务类

public class MyAccessibilityService extends AccessibilityService {@Overridepublic void onServiceConnected() {Log.d("Accessibility", "无障碍服务已启动");}@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {int eventType = event.getEventType();if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED ||eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {AccessibilityNodeInfo rootNode = getRootInActiveWindow();if (rootNode == null) return;List<String> texts = getAllTexts(rootNode);Log.d("ScreenTexts", "捕获文本: " + TextUtils.join(", ", texts)); sendTextToActivity(texts);rootNode.recycle(); // 释放资源}}private List<String> getAllTexts(AccessibilityNodeInfo node) {List<String> texts = new ArrayList<>();traverseNode(node, texts);return filterUniqueTexts(texts);}private void traverseNode(AccessibilityNodeInfo node, List<String> texts) {if (node == null) return;CharSequence text = node.getText();if (text != null && !TextUtils.isEmpty(text)) {texts.add(text.toString().trim());}for (int i = 0; i < node.getChildCount(); i++) {AccessibilityNodeInfo child = node.getChild(i);if (child != null) {traverseNode(child, texts);child.recycle(); // 必须回收子节点}}}private List<String> filterUniqueTexts(List<String> list) {Set<String> uniqueSet = new HashSet<>(list);return new ArrayList<>(uniqueSet);}private void sendTextToActivity(List<String> texts) {Intent intent = new Intent("ACTION_UPDATE_TEXT");intent.putStringArrayListExtra("texts", new ArrayList<>(texts));sendBroadcast(intent);}@Overridepublic void onInterrupt() {}
}

启用无障碍服务

需要在系统设置中启用应用的无障碍服务。
请添加图片描述

运行效果

当界面内容变化时(如打开新页面),服务会自动捕获所有可见文本,并打印出来。

在我们在设置页面开启无障碍服务的时候
开启无障碍服务

TextAccessibilityService com.example.myapplication            I  无障碍服务已启动
TextAccessibilityService com.example.myapplication            I  捕获文本:TextAccessibility_tip”快捷方式, 关闭, 设置, 选项, 使用“TextAccessibility_tip, TextAccessibilityDesc, TextAccessibility_tip

打开首页
打开首页

TextAccessibilityService  com.example.myapplication            I  捕获文本: 设置, 文件, 时钟, 拨打电话, MyApplication, WebView Browser Tester, 相机, 日历, TMoble, 通讯录, Search, 搜索应用, 短信, 图库
TextAccessibilityService  com.example.myapplication            I  捕获文本: 拨打电话, 短信, WebView Browser Tester, 相机, 图库

打开MainActivity
打开MainActivity

TextAccessibilityService  com.example.myapplication            I  捕获文本: Hello World!

注意事项

权限限制

  • Android 11+ 需要 android.permission.QUERY_ALL_PACKAGES 权限才能获取其他应用的内容。

  • 敏感场景(如密码输入)可能无法捕获文本。

性能优化

  • 避免频繁遍历控件树(可增加事件过滤)。

  • 使用 postDelayed 防抖处理高频事件。

http://www.xdnf.cn/news/694657.html

相关文章:

  • 2025.05.28【Choropleth】群体进化学专用图:区域数据可视化
  • WifiEspNow库函数详解
  • 【时时三省】(C语言基础)函数的递归调用例题
  • Flask集成pyotp生成动态口令
  • DeepSeek实战:打造智能数据分析与可视化系统
  • 用 Python 实现了哪些办公自动化
  • canal高可用配置
  • Java开发之定时器学习
  • LVS -DR
  • 每日算法 -【Swift 算法】正则表达式匹配:支持 `.` 和 `*`
  • 如何设计高效的数据湖架构:存储策略、Schema 演进与数据生命周期管理
  • 基于51单片机的音乐盒汽车喇叭调音量proteus仿真
  • 基于Doc2Vec的Markdown文档分类实战:从预处理到模型评估
  • 部署swagger接口文档到云服务器
  • ZooKeeper 命令操作
  • Gin项目脚手架与标配组件
  • 网络协议DHCP
  • YOLO 系列算法的参数量
  • Java大师成长计划之第33天:应用监控与日志管理
  • 顺序表与链表专项训练:在 LeetCode 实战中深化数据结构理解
  • 力扣 秋招 打卡第一天 2025年5月28日 Java
  • Vim 中设置插入模式下输入中文
  • 考研系列-操作系统:第一章、计算机系统概述
  • freecad TechDraw工作台中虚线(隐藏线)的实现方式
  • 桥梁进行3D建模时的数据采集、存储需求及技术参数
  • 监控 Oracle Cloud 负载均衡器:使用 Applications Manager 释放最佳性能
  • android平台驱动开发(六)--Makefile和Kconfig简介
  • vue 实现鼠标放上后显示,挪开后隐藏(点击显示/隐藏)
  • 【微波遥感第一期】基本概念
  • OpenCV CUDA模块直方图计算------在 GPU 上计算图像直方图的函数calcHist()