辅助功能(AccessibilityService)其实是一个Android系统提供给的一种服务,本身是继承Service类的。这个服务提供了增强的用户界面,旨在帮助残障人士使用android设备和应用,在后台运行,可以监听用户界面的一些状态转换,例如页面切换、焦点改变、通知、Toast等,并在触发AccessibilityEvents时由系统接收回调。后来被开发者另辟蹊径,用于一些插件开发,比如微信红包助手,还有一些需要监听第三方应用的插件。
原理
AccessibilityService具有很多强大的功能。但是从开发者的角度看,其实最主要的就是提供两种功能:查找界面元素,实现模拟点击。这也是我们实现自动抢红包软件的关键。当View、ViewGroup、TextView等控件这些状态变化时控件会回调系统API,API系统然后对这些对象的数据进行组装,为了数据的安全性,系统会重新创建一些对象(AccessibilityEvent、AccessibilityNodeInfo)来间接保存这些数据,然后通过跨进程将这些数据返回给对应的Service中。
使用范围
辅助功能不可能直接操作外部对象,辅助功能只能在本进程调用指定系统方法,由系统再分发给指定外部对象,辅助功能做的事基本和用户能做的差不多。
注意事项
AccessibilityEvent、AccessibilityNodeInfo里面的所有set方法均无用(这些方法是系统调用把数据塞进去用的),我们能做的只有:get、is、find等获取数据的方法,以及极少的操作performAction,dispatchGesture等。
使用步骤
1. 配置自己的辅助功能服务
对于辅助功能类的配置有两种方式:
(1)在onServiceConnected() 中配置(不推荐,部分属性可能无法设置)
/**
* 当系统连接上你的服务时被调用
*/
@Override
protected void onServiceConnected() {
//设置监听的应用包名(微信和qq)
AccessibilityServiceInfo info = getServiceInfo();
info.packageNames = new String[]{WX_PKG, QQ_PKG};
setServiceInfo(info);
super.onServiceConnected();
}
(2)在XML中配置(推荐)
新建配置 service_config.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"
android:canRetrieveWindowContent="true"
android:notificationTimeout="100"
android:packageNames="com.tencent.mm"
android:description="@string/accessibility_description"/>
这里来简单介绍一下这些配置:
accessibilityEventTypes 过滤事件类型
- typeAllMask / AccessibilityEvent.TYPES_ALL_MASK:全局事件响应
- typeViewClicked / AccessibilityEvent.TYPE_VIEW_CLICKED :点击事件
accessibilityFeedbackType 反馈类型
- feedbackGeneric / AccessibilityServiceInfo.FEEDBACK_GENERIC : 通用的反馈
- feedbackAudible / AccessibilityServiceInfo.FEEDBACK_AUDIBLE : 声音反馈
- feedbackSpoken / AccessibilityServiceInfo.FEEDBACK_SPOKEN : 语音反馈
canRetrieveWindowContent 请求访问权限
packageNames 需要监听的包名列表
notificationTimeout 响应时间设置
2. 在AndroidManifest.xml中声明服务和配置
<service
android:name=".PacketService"
android:enabled="true"
android:exported="true"
android:label="@string/lab_name"
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/service_config"/>
</service>
3. 创建自己的辅助功能类
编写自己的辅助服务类,需要继承AccessibilityService类。
生命周期
- onServiceConnected()
连接成功 - onInterrupt()
服务中断 - onUnbind(Intent intent)
服务关闭 - onAccessibilityEvent()
接收事件,这个是辅助类的关键方法。通过这个函数可以接收系统发送来的AccessibilityEvent,接收来的AccessibilityEvent是经过过滤的,过滤是在配置工作时设置的。下面说一下配置自己的辅助服务。
新建PacketService.java类
/**
* 必须重写的方法:此方法用了接受系统发来的event。在你注册的event发生是被调用。在整个生命周期会被调用多次。
*/
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
//得到对应的事件类型,这里有很多很多种的事件类型,具体可以自行翻阅AccessibilityEvent类中的定义。
int eventType = event.getEventType();
LogUtil.d("eventType ===> " + eventType);
switch (eventType) {
// 通知栏事件
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
//获取通知栏消息的文字
List<CharSequence> texts =