AccessibilityService 从入门到出轨

一、AccessibilityService

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

官方文档

二、AccessibilityService 开发流程

  1. 确定执行脚本的APK安装包
  2. 通过UIAutomator 获取包名及UI控件ID
  3. 编写脚本代码
  4. 调试、兼容性处理

三、开发一款服务助手

1、获取脚本事件ID

  1. UIAutomator 入口:Android->sdk->tools->bin-> uiautomatorviewer

    image.png

  2. 按照下图指示,获取对应的包名与视图ID

    image.png

2、实现服务助手

AccessibilityService主要是实现onAccessibilityEvent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class AccessibilitySampleService extends AccessibilityService{

@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
}
}
AccessibilityService
方法名 方法说明
disableSelf() 禁用当前服务,也就是在服务可以通过该方法停止运行
findFoucs(int falg) 查找拥有特定焦点类型的控件
getRootInActiveWindow() 如果配置能够获取窗口内容,则会返回当前活动窗口的根结点
onAccessibilityEvent(AccessibilityEvent event) 有关AccessibilityEvent事件的回调函数.系统通过sendAccessibiliyEvent()不断的发送AccessibilityEvent到此处
performGlobalAction(int action) 执行全局操作,比如返回,回到主页,打开最近等操作,此方法可以模拟用户点击返回键和home键
setServiceInfo(AccessibilityServiceInfo info) 设置当前服务的配置信息
getSystemService(String name) 获取系统服务
onKeyEvent(KeyEvent event) 如果允许服务监听按键操作,该方法是按键事件的回调,需要注意,这个过程发生了系统处理按键事件之前
onServiceConnected() 系统成功绑定该服务时被触发,也就是当你在设置中开启相应的服务,系统成功的绑定了该服务时会触发,通常我们可以在这里做一些初始化操作
AccessibilityEvent
字段名 字段说明
TYPE_NOTIFICATION_STATE_CHANGED 通知栏状态变化
TYPE_VIEW_CLICKED 视图被点击
TYPE_WINDOW_CONTENT_CHANGED 窗口内容变化
TYPE_WINDOW_STATE_CHANGED 窗口状态变化

3、AndroidManifest.xml注册服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 注册辅助功能服务-->
<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>
在资源文件夹新增xml文件夹,新建accessibility_config文件,代码如下
1
2
3
4
5
6
7
8
<?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:description="@string/accessibility_desc"
android:notificationTimeout="100" />
<!--accessibility_desc:码君助手,让你的手机更智能一点 -->

accessibility_config说明

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

4、编写执行脚本

1
2
3
4
5
6
7
8
9
10
11
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() 获取子节点

5、应用场景

  1. 微信抢红包助手
  2. 微信自动回复助手、支付助手、听歌助手
  3. 自动化测试
  4. 浏览器拦截(一旦打开自动输入自定义网址)
  5. 刷点赞评论阅读量


1.如果本文帮到了您,不妨点一下右下角的 分享到 按钮。
2.除非注明,本博文章均为原创,转载请以链接形式标明本文地址。
3.本博文章只代表博主当时的观点或结论,与博主公司没有任何关系。