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_CLICKEDView.performClick() 中触发
  • TYPE_VIEW_TEXT_CHANGEDTextView 中携带 fromIndex/removedCount/addedCount/beforeText
  • TYPE_WINDOW_CONTENT_CHANGED → 通过 notifySubtreeAccessibilityStateChanged() 沿 View 树向上传播至 ViewRootImpl
  • TYPE_WINDOW_STATE_CHANGEDViewRootImpl 在 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

相关推荐
智购科技无人售货机工厂1 小时前
2026自动售货机热敏打印模块集成:从串口驱动到小票自动裁切的工程实践~YH
android·stm32·单片机·嵌入式硬件·系统架构
A13345552 小时前
苹果安卓手机播放器推荐:2026无广告4K怎么选
android·智能手机
hunterandroid3 小时前
ContentProvider 跨进程数据共享实战
android·前端
天空之城--4 小时前
Android输入法子系统深度解析
android
天空之城--5 小时前
Android全链路性能优化:从原理到实践的终极指南
android·性能优化
Meteors.5 小时前
Android 性能优化:05.CPU优化
android·性能优化
石头猫灯6 小时前
一次 CMS 被黑实录:完整事件思路梳理
android·学习
zhonyu鱼6 小时前
Escrcpy:用电脑键盘鼠标操作安卓手机的跨平台投屏工具
android·计算机外设·电脑
千里马学框架7 小时前
安卓开机性能优化:如何安全高效地裁剪 SystemService
android·智能手机·framework·wms·手机·性能·车载