Android AccessibilityService使用方法

  1. 原理
    大致简述一下,谷歌已经在View、ViewGroup、TextView等控件的文字改变、滑动、UI变化埋下了接口,当这些状态变化时控件会回调系统API,API系统然后对这些对象的数据进行组装,为了数据的安全性,系统会重新创建一些对象(AccessibilityEvent、AccessibilityNodeInfo)来间接保存这些数据,然后通过跨进程将这些数据返回给对应的Service中。

  2. 使用范围
    首先,辅助功能不可能直接操作外部对象,辅助功能只能在本进程调用指定系统方法,由系统再分发给指定外部对象,辅助功能做的事基本和用户能做的差不多(比如回复微信, 微信抢红包)

AccessibilityService用法

  1. 首先, AccessibilityService本质上也是一个Service, 所以在Manifest.xml 中还是需要注册对应的Service内容, 并且声明权限, 示例如下:
<service
            android:name=".RobService"
            android:enabled="true"
            android:exported="true"
            android:label="学习强国"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService" />
        </intent-filter>

        <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/myaccessibility"/>
        </service>

其中resource中的配置项是单独创建一个myaccessibility.xml文件

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"

    android:accessibilityEventTypes="typeAllMask" // 监听的事件类型, 这里表示全局监听
    android:accessibilityFeedbackType="feedbackGeneric" //反馈类型, 这里表示通用反馈
    android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows|flagIncludeNotImportantViews"
    android:canRetrieveWindowContent="true" //表示该服务能否访问活动窗口中的内容.也就是如果你希望在服务中获取窗体内容的话,则需要设置其值为true.
    android:notificationTimeout="100" // 接受事件的时间间隔
    android:canPerformGestures="true" //分发手势
    android:packageNames="com.tencent.mm"/>
  1. 在注册服务完成后, 就可以创建一个Service继承AccessibilityService, 并且实现它的onServiceConnectedonAccessibilityEvent方法, 其中, 在onServiceConnected方法中放一些资源的初始化操作, 此方法会在开启了AccessibilityService权限的时候被调用. 在onAccessibilityEvent实现对事件的处理, 比如屏幕改变事件, 消息通知事件.

  2. 控件的查找与操作
    控件的操作主要分为几个步骤:

    1. 获取到当前界面的根节点AccessibilityNodeInfo rootNode = getRootInActiveWindow();

    2. 通过id或者text文本查找到对应的节点

      • 在sdk-tools/tools目录下, 有一个monitor.bat脚本, 双击这个脚本打开Android Device Monitor
      • 在电脑连接了安卓手机并且开启了USB调试模式的情况下, Android Device Monitor会显示出对应的手机, 点击上面的Dump View按钮, 此时工具会自动对当前手机界面进行分析, 并生成一个dump
      • 最后得到类似下图, 用鼠标移动到对应的控件上, 即可看到控件的属性和文本等


        截图

        控件属性
    3. 对节点进行操作, 这里要注意到, 有一些程序做了特殊处理, 有时候在Android Device Monitor看到clickable属性为true, 但不一定它就会响应click事件, 是否响应事件要按实际情况分析.

//获取当前聊天页面的根布局
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
List<AccessibilityNodeInfo> listChat = rootNode.findAccessibilityNodeInfosByViewId("android:id/text1"); //根据id查找控件
//List<AccessibilityNodeInfo> listChat = rootNode.findAccessibilityNodeInfosByText("发送"); //根据文本查找控件
for (AccessibilityNodeInfo nodeInfo : listChatRecord) {
   nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK); //点击控件
}
  1. 手势
    Android提供了特殊类型的触摸屏事件,如捏合,双击,滚动,长按和退缩。这些都被称为手势。
 //发送一个点击事件
Path mPath=new Path();//线性的path代表手势路径,点代表按下,封闭的没用
mPath.moveTo(500, 500);
service.dispatchGesture(new GestureDescription.Builder().addStroke(new GestureDescription.StrokeDescription
(mPath, 手势开始时间比如立即开始0, 手势总时长比如100)).build(), 回调函数(可以为null), 回调的线程(null表示主线程));

扩展使用

  1. 使用webview通过js调用android代码
    在android的方法定义中, 加上@JavaScriptInterface注释后, 在webView.addJavascriptInterface(new JsInterface(), "Android");
    然后在js中执行"Android.方法名"

附录

  • accessibilityEventTypes的取值
    | constant | value | 描述 |
    | - | - | - |
    | typeAllMask|ffffffff|所有类型的事件
    |typeAnnouncement|4000|一个应用产生一个通知事件
    |typeAssistReadingContext|1000000|辅助用户读取当前屏幕事件
    |typeContextClicked|800000|view中上下文点击事件
    |typeGestureDetectionEnd|80000|监测到的手势事件完成
    |typeGestureDetectionStart|40000|开始手势监测事件
    |typeNotificationStateChanged|40|收到notification弹出消息事件
    |typeTouchExplorationGestureEnd|400|触摸浏览事件完成
    |typeTouchExplorationGestureStart|200|触摸浏览事件开始
    |typeTouchInteractionEnd|200000|用户触屏事件结束
    |typeTouchInteractionStart|100000|触摸屏幕事件开始
    |typeViewAccessibilityFocusCleared|10000|无障碍焦点事件清除
    |typeViewAccessibilityFocused|8000|获得无障碍的焦点事件
    |typeViewClicked|1|点击事件
    |typeViewFocused|8|view获取到焦点事件
    |typeViewHoverEnter|80|一个view的悬停事件
    |typeViewHoverExit|100|一个view的悬停事件结束,悬停离开该view
    |typeViewLongClicked|2|view的长按事件
    |typeViewScrolled|1000|view的滚动事件,adapterview、scrollview
    |typeViewSelected|4|view选中,一般是具有选中属性的view,例如adapter
    |typeViewTextChanged|10|edittext中文字发生改变的事件
    |typeViewTextSelectionChanged|2000|edittext文字选中发生改变事件
    |typeViewTextTraversedAtMovementGranularity|20000|UIanimator中在一个视图文本中进行遍历会产生这个事件,多个粒度遍历文本。一般用于语音阅读context
    |typeWindowContentChanged|800|窗口的内容发生变化,或者更具体的子树根布局变化事件
    |typeWindowStateChanged|20|新的弹出层导致的窗口变化(dialog、menu、popupwindow)
    |typeWindowsChanged|400000|屏幕上的窗口变化事件,需要API 21+

  • `accessibilityFeedbackType 此服务提供的反馈类型

constant value 描述
feedbackAllMask ffffffff 取消所有的可用反馈方式
feedbackAudible 4 可听见的(非语音反馈)
feedbackGeneric 10 通用反馈
feedbackHaptic 2 触觉反馈(震动)
feedbackSpoken 1 语音反馈
feedbackVisual 8 视觉反馈
  • accessibilityFlags 辅助功能附加的标志,多个使用 ' | '分隔
constant value 描述
flagDefault 1 默认的配置
flagEnableAccessibilityVolume 80 这个标志要求系统内所有的音频通道,使用由STREAM_ACCESSIBILTY音量控制USAGE_ASSISTANCE_ACCESSIBILITY
flagIncludeNotImportantViews 2 表示可获取到一些被表示为辅助功能无权获取到的view
flagReportViewIds 10 使用该flag表示可获取到view的ID
flagRequestAccessibilityButton 100 如果辅助功能可用,提供一个辅助功能按钮在系统的导航栏 API 26+
flagRequestEnhancedWebAccessibility 8 此类扩展的目的是为WebView中呈现的内容提供更好的辅助功能支持。这种扩展的一个例子是从一个安全的来源注入JavaScript。如果至少有一个具有此标志的辅助功能服务, 则系统将使能增强的web辅助功能。因此, 清除此标志并不保证该设备不会使能增强的web辅助功能, 因为可能有另一个使能的服务在使用它。
flagRequestFilterKeyEvents 20 能够监听到系统的物理按键
flagRequestFingerprintGestures 200 监听系统的指纹手势 API 26+
flagRequestTouchExplorationMode 4 系统进入触控探索模式。出现一个鼠标在用户的界面
flagRetrieveInteractiveWindows 40 该标志知识的辅助服务要访问所有交互式窗口内容的系统,这个标志没有被设置时,服务不会收到TYPE_WINDOWS_CHANGE事件。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容