Android 无障碍开发入门

一、AccessibilityService

根据官方的介绍,是指开发者通过增加类似contentDescription的属性,从而在不修改代码的情况下,让残障人士能够获得使用体验的优化,大家可以打开AccessibilityService来试一下,点击区域,可以有语音或者触摸的提示,帮助残障人士更好的使用App

现在被广泛应用在自动化,比如自动抢红包,抖音自动关注点赞等

官方文档:

https://developer.android.com/guide/topics/ui/accessibility/service

二、AccessibilityService 开发流程

1.确定执行脚本的APK安装包

2.通过UIAutomator 获取包名及UI控件ID,或者下载一个开发者助手apk,也可以进行控件ID获取,代码君已经帮你下载好了,需要自取

http://share.dmjzy.cn/f/17143538-501591536-a374b2(访问密码:8401

3.编写脚本代码

4.调试、兼容性处理

三、核心代码

1.AccessibilityService主要是实现onAccessibilityEvent

public class AccessibilitySampleService extends AccessibilityService{

    /**当无障碍服务连接之后回调*/
   @Override
   public void  onServiceConnected() {
        super.onServiceConnected()
    }

    /**当触发了需要监听的无障碍事件后回调*/
   @Override 
   public void onAccessibilityEvent(AccessibilityEvent event){
       // 获取包名
       String pkgName = event.getPackageName().toString();
       int eventType = event.getEventType();

       AccessibilityOperator.getInstance().updateEvent(this, event);
       //过滤出目标包,如果要检测所有包,可以去掉此判断
       if (pkgName.equals(pageName)) {
           AccessibilityLog.printLog("eventType: " + eventType + " pkgName: " + pkgName);

           switch (eventType) {
               case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                   //执行具体的脚本
                   toOperator();
                   break;
               case AccessibilityEvent.TYPE_VIEW_CLICKED:
                   break;
               case AccessibilityEvent.TYPE_VIEW_LONG_CLICKED:
                   break;
               case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
                   break;
           }
       }
   } 
   /**无障碍服务断开后回调*/
   @Override 
   public void onInterrupt(){
       // TODO Auto-generated method stub 
   }
}

方法说明

1. onServiceConnected

当声明的无障碍服务连接之后, 系统会回调此方法. 在这个方法里, 可以做一些初始化工作. 比如保存服务的实例 标识服务连接的状态等.

也可以通过

android.accessibilityservice.AccessibilityService#getServiceInfo

动态更改xml配置文件中声明的无障碍配置信息.

2. onAccessibilityEvent

当监听的事件触发时, 系统会回调此方法, 比如view被点击了 window内容改变了等.

可以用

android.view.accessibility.AccessibilityRecord#getSource

获取对象AccessibilityNodeInfo, 这个对象就是无障碍操作的核心对象, 通常可以理解为android开发中的view控件.

可以通过AccessibilityNodeInfo对象, 进行控件的点击操作 输入文本操作 滚动操作 获取文本操作等

3. onInterrupt

当中途关闭了无障碍服务时回调, 通常这个时候无障碍服务不可用, 调用api都会失败.

4. AccessibilityService 其他方法说明

方法名 方法说明
disableSelf() 禁用当前服务,也就是在服务可以通过该方法停止运行
findFoucs(int falg) 查找拥有特定焦点类型的控件
getRootInActiveWindow() 如果配置能够获取窗口内容,则会返回当前活动窗口的根结点
performGlobalAction(int action) 执行全局操作,比如返回,回到主页,打开最近等操作,此方法可以模拟用户点击返回键和home键,操作见下面的官方文档
setServiceInfo(AccessibilityServiceInfo info) 设置当前服务的配置信息
getSystemService(String name) 获取系统服务
onKeyEvent(KeyEvent event) 如果允许服务监听按键操作,该方法是按键事件的回调,需要注意,这个过程发生了系统处理按键事件之前

更多AccessibilityService参数说明见官方文档:

https://developer.android.google.cn/reference/kotlin/android/accessibilityservice/AccessibilityService

AccessibilityEvent

字段名 字段说明
TYPE_NOTIFICATION_STATE_CHANGED 通知栏状态变化
TYPE_VIEW_CLICKED 视图被点击
TYPE_WINDOW_CONTENT_CHANGED 窗口内容变化
TYPE_WINDOW_STATE_CHANGED 窗口状态变化,即切换activity

2. AndroidManifest.xml注册服务

<!-- 注册辅助功能服务-->
       <service
           android:name=".AccessibilitySampleService"
           android:exported="true"
           android:label="码君助手"
           android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
           android:process=":BackgroundService">
           <intent-filter>
               <action android:name="android.accessibilityservice.AccessibilityService" />
           </intent-filter>
           <!--       通过xml文件完成辅助功能相关配置,也可以在onServiceConnected中动态配置-->
           <meta-data
               android:name="android.accessibilityservice"
               android:resource="@xml/accessibility_config" />
       </service>

3. 在资源文件夹新增xml文件夹,新建accessibility_config文件,代码如下

<?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:canRetrieveWindowContent="true"
    android:canPerformGestures="true"
    android:description="@string/accessibility_desc"
    android:notificationTimeout="10" />

<!--  canPerformGestures  //申请手势权限-->
<!--accessibility_desc:码君助手,让你的手机更智能一点 -->

accessibility_config说明

官方文档说明:

https://developer.android.google.cn/reference/android/R.styleable#AccessibilityService

这里列举一些比较常用的

字段名 字段说明
accessibilityEventTypes 表示该服务对界面中的哪些变化感兴趣,即哪些事件通知,比如窗口打开,滑动,焦点变化,长按等.具体的值可以在AccessibilityEvent类中查到,如typeAllMask表示接受所有的事件通知
accessibilityFeedbackType 表示反馈方式,比如是语音播放,还是震动。feedbackGeneric代表所有
canRetrieveWindowContent 表示该服务能否访问活动窗口中的内容.也就是如果你希望在服务中获取窗体内容的化,则需要设置其值为true
notificationTimeout 接受事件的时间间隔,通常将其设置为100即可
packageNames 表示对该服务是用来监听哪个包的产生的事件。如果不写代表监听所有的应用。中间可以用";"来分割。
canPerformGestures 表示可以执行手势属性
canTakeScreenshot 是否能够截屏

4、编写执行脚本

try {
           Thread.sleep(2000);
           AccessibilityOperator.getInstance().clickById("com.xxxx.packagename:id/btn_later");// 关闭弹框

           Thread.sleep(1000);
           AccessibilityOperator.getInstance().clickById("com.xxxx.packagename:id/tab_work");//切换到工作tab
           AccessibilityLog.printLog("切换到工作tab: ");

       } catch (InterruptedException e) {
           e.printStackTrace();
       }

AccessibilityNodeInfo

方法名 方法说明
findAccessibilityNodeInfosByText() 通过字符串查找节点元素
findAccessibilityNodeInfosByViewId() 通过视图id查找节点元素
performAction() 在节点上执行一个动作,比如点击、向上滑动等,更多操作见下面的官方文档
getParent() 获取父节点
getChild() 获取子节点
isEnabled() 判断节点是否激活
isClickable() 判断节点是否可以点击
isScrollable() 判断节点是否可以滚动
isSelected() 判断节点是否选中
isPassword() 判断节点是否是密码输入框
isFocusable() 判断节点是否可以获取焦点
getText() 获取节点的文本信息
getContentDescription() 节点的内容描述
getViewIdResourceName() 获取节点控件的id ,获取到的值大概是这样的:com.ss.android.ugc.aweme:id/afy
getBoundsInScreen() 获取节点在屏幕中的位置
getClassName() 获取节点的类型/类名,值:android.widget.LinearLayout
getChild() 获取子节点的AccessibilityNodeInfo信息

更多请查看官方文档:

https://developer.android.google.cn/reference/android/view/accessibility/AccessibilityNodeInfo

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容