Android 7系统无障碍服务(四)AccessibilityEvent 的产生与投递

Android 7系统无障碍服务(四)------AccessibilityEvent 的产生与投递

系列目录 :第一篇:全景图与架构概览 | [第二篇:AccessibilityManagerService 启动与初始化](#第二篇:AccessibilityManagerService 启动与初始化) | 第三篇:无障碍服务的注册与绑定 | [第四篇:AccessibilityEvent 的产生与投递](#第四篇:AccessibilityEvent 的产生与投递) | [第五篇:AccessibilityNodeInfo 的构建与查询](#第五篇:AccessibilityNodeInfo 的构建与查询) | [第六篇:输入事件拦截与 TouchExplorer](#第六篇:输入事件拦截与 TouchExplorer) | [第七篇:手势分发与 KeyEvent 处理](#第七篇:手势分发与 KeyEvent 处理) | 第八篇:放大镜与辅助功能特性


上一篇分析了无障碍服务从 Manifest 声明到被 AMS 绑定并就绪的全过程。服务就绪后,系统如何将 UI 变化告知它?答案就是 AccessibilityEvent。本篇完整梳理 AccessibilityEvent 从 View 层产生、经 AccessibilityManager 跨进程投递、在 AMS 中排队与调度、最终到达 AccessibilityService 的全链路。

一、AccessibilityEvent 是什么

AccessibilityEvent 是系统将 UI 变化通知无障碍服务的载体。它携带了"什么组件发生了什么变化"的上下文信息。

源码路径 :frameworks/base/core/java/android/view/accessibility/AccessibilityEvent.java

java 复制代码
public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable {
    // 核心事件类型(部分)
    public static final int TYPE_VIEW_CLICKED            = 0x00000001;
    public static final int TYPE_VIEW_LONG_CLICKED       = 0x00000002;
    public static final int TYPE_VIEW_SELECTED           = 0x00000004;
    public static final int TYPE_VIEW_FOCUSED            = 0x00000008;
    public static final int TYPE_VIEW_TEXT_CHANGED       = 0x00000010;
    public static final int TYPE_WINDOW_STATE_CHANGED    = 0x00000020;
    public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
    public static final int TYPE_WINDOW_CONTENT_CHANGED  = 0x00000800;
    public static final int TYPE_VIEW_SCROLLED           = 0x00001000;
    public static final int TYPE_ANNOUNCEMENT            = 0x00004000;
    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED   = 0x00008000;
    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
    public static final int TYPES_ALL_MASK               = 0xFFFFFFFF;

    private int mEventType;
    private CharSequence mPackageName;
    private long mEventTime;
    // 继承自 AccessibilityRecord: mSourceNodeId, mWindowId, mClassName, mText 等
}

二、事件在 View 层的产生

源码路径 :frameworks/base/core/java/android/view/View.java

java 复制代码
public void sendAccessibilityEvent(int eventType) {
    if (mAccessibilityDelegate != null) {
        mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
    } else {
        sendAccessibilityEventInternal(eventType);
    }
}

private void sendAccessibilityEventInternal(int eventType) {
    if (AccessibilityManager.getInstance(mContext).isEnabled()) {
        sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
    }
}

public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
    if (!isShown()) return;  // 不可见 View 不发送
    onInitializeAccessibilityEvent(event);
    if (mParent != null) {
        mParent.requestSendAccessibilityEvent(this, event);
    }
}

两个过滤点:isEnabled() 全局开关检查 + isShown() 可见性检查。

典型触发场景:

  • TYPE_VIEW_CLICKED → View.performClick() 中触发
  • TYPE_VIEW_TEXT_CHANGED → TextView 中携带 fromIndex/removedCount/addedCount/beforeText
  • TYPE_WINDOW_CONTENT_CHANGED → 通过 notifySubtreeAccessibilityStateChanged() 沿 View 树向上传播至 ViewRootImpl
  • TYPE_WINDOW_STATE_CHANGED → ViewRootImpl 在 Activity/Dialog/输入法窗口变化时主动发送

onInitializeAccessibilityEvent() 各控件可重写来填充特有信息(如 CompoundButton 填充 checked 状态)。

三、AccessibilityManager 客户端层

源码路径 :frameworks/base/core/java/android/view/accessibility/AccessibilityManager.java

java 复制代码
public void sendAccessibilityEvent(AccessibilityEvent event) {
    synchronized (mLock) {
        if (!mIsEnabled) {
            event.recycle();
            return;
        }
        // 通过 Handler 异步发送,避免阻塞 UI 线程
        mHandler.sendMessage(mHandler.obtainMessage(
                DO_SET_ACCESSIBILITY_EVENT, event));
    }
}

关键设计:异步发送 。sendAccessibilityEvent() 通常在 UI 线程被调用,如果同步等待 Binder 调用完成会造成 UI 卡顿。通过 Han

相关推荐
alexhilton6 小时前
模块化Jetpack Compose架构
android·kotlin·android jetpack
厮年断弦8 小时前
AI 辅助开发实录:一周做完一个 Android 本地音乐播放器,这些坑替你踩了
android
hai_android8 小时前
InputStage 责任链核心执行流程
android·android studio·android jetpack
mmsx11 小时前
Android 测绘计算工程化:七四参数、高程拟合与单位系统
android·kotlin
我是场13 小时前
我的NPI项目之-Touch的EE特性
android·arm开发
天空之城--13 小时前
Android一周动态:AI编程、Compose与车载生态新信号
android·flutter
恋猫de小郭14 小时前
Dart 4.0 要彻底移除 dart:mirrors,Augmentations 应该要来了
android·前端·flutter
Carson带你学Android16 小时前
Gemini 4 Argon 发布:对 Android 开发者意味着什么?
android·ai编程
事圆则缓17 小时前
Kotlin Flow、StateFlow、SharedFlow 全解析:冷流、热流与 Android 状态管理
android·kotlin·php
应用市场17 小时前
把旧 Pixel 变成相册备份中转站(上):Mac 到安卓的照片传输工具设计——流式上传、sha256 校验、adb forward 与 Bonjour
android·macos·adb·kotlin·swift