微信红包自打出世以来就极其受欢迎,抢红包插件可谓红极一时.今天,我们重新谈谈抢红包插件的哪些事儿.本质上,抢红包插件的原理不难理解,其过程就是在收到红包时,自动模拟点击.做过自动化UI测试的童鞋应该非常熟悉了.那么问题来了,我们怎么知道有没有红包,又怎么模拟点击操作呢?在PC端我们有按键精灵,那么在Android设备上呢?话说也偶然,Google为了让Android系统更实用,为用户提供了无障碍辅助服务(AccessibilityService
).
AccessibilityService
运行在后台,并且能够收到由系统发出的一些事件(AccessibilityEvent
,这些事件表示用户界面一系列的状态变化),比如焦点改变,输入内容变化,按钮被点击了等等,该种服务能够请求获取当前活动窗口并查找其中的内容.换言之,界面中产生的任何变化都会产生一个时间,并由系统通知给AccessibilityService
.这就像监视器监视着界面的一举一动,一旦界面发生变化,立刻发出警报.
是不是感觉很棒?接下来,让我们来看看如何AccessibilityService的基本使用,在不同的阶段,对其中的一些点做深入的说明,之后我们从实际应用出发,探讨其中的一些使用场景.
基础使用
1. 创建服务类
编写自己的服务类,需要继承AccessibilityService类.其中要实现onAccessibilityEvent(AccessibilityEvent event)
及onInterruput()
两个重要的方法:
public class RobService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
//handle
}
@Override
public void onInterrupt() {
}
@Override
protected void onServiceConnected() {
}
这里我们简单的介绍一下该类常用的方法:
方法 | 作用 |
---|---|
disableSelf() |
禁用当前服务,也就是在服务可以通过该方法停止运行 |
findFoucs(int falg) |
查找拥有特定焦点类型的控件 |
getRootInActiveWindow() |
如果配置能够获取窗口内容,则会返回当前活动窗口的根结点 |
getSeviceInfo() |
获取当前服务的配置信息 |
onAccessibilityEvent(AccessibilityEvent event ) |
有关AccessibilityEvent事件的回调函数.系统通过sendAccessibiliyEvent()不断的发送AccessibilityEvent到此处 |
performGlobalAction(int action) |
执行全局操作,比如返回,回到主页,打开最近等操作 |
setServiceInfo(AccessibilityServiceInfo info) |
设置当前服务的配置信息 |
getSystemService(String name) |
获取系统服务 |
onKeyEvent(KeyEvent event) |
如果允许服务监听按键操作,该方法是按键事件的回调,需要注意,这个过程发生了系统处理按键事件之前 |
onServiceConnected() |
系统成功绑定该服务时被触发,也就是当你在设置中开启相应的服务,系统成功的绑定了该服务时会触发,通常我们可以在这里做一些初始化操作 |
更详细的内容参见官方文档
2. 声明服务
像其他Service服务一样,需要在AndroidManifest.xml中声明.除此之外,该服务还必须配置以下两项:
- 配置
<intent-filter>
,其name为固定的android.accessibilityservice.AccessibilityService - 声明BIND_ACCESSIBILITY_SERVICE权限,以便系统能够绑定该服务(4.1版本后要求)
注意:任何一点配置错误,系统都检测不到该服务,因此其固定配置如下:
<service
android:name=".RobService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
</service>
3. 配置服务类
在AndroidManifest.xml声明了该服务之后,接下来就是需要对该服务进行一些参数设置了.该服务能够被配置用来接受指定类型的事件,监听指定package,检索窗口内容,获取事件类型的时间等等.目前有两种配置方法:
- 4.0之后提供了可以通过
<meta-data>
标签进行配置 - 通过
setServiceInfo()
进行配置
1. 通过<meta-data>
进行配置
在manifest生命的servce中提供一个meta-data标签,然后通过android:resource指定相应的配置文件(在res目录下创建xml文件,并在其中创建配置文件accessibility.xml):
<service
android:name=".RobService"
android:enabled="true"
android:exported="true"
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/accessibility"/>
</service>
接下来我们来看accessibility.xml的相关配置:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:notificationTimeout="100"
android:packageNames="com.tencent.mm" />
后面,我们在只需要仿照该配置文件根据自己的需求进行修改即可.下面我们会对这些属性进行介绍.
2. 通过setServiceInfo(AccessibilityServiceInfo info)
也可以通过setServiceInfo(AccessibilityServiceInfo)
为其配置信息,除此之外,通过该方法可以在运行期间动态修改服务配置.需要注意,该方法只能用来配置动态属性:eventTypes,feedbackType,flags,notificaionTimeout及packageNames.
通常是在