AccessibilityService 是 Android 提供的一种特殊服务,主要用于帮助残障用户(例如视力或肢体障碍者)更方便地使用设备。它可以监听和响应设备界面上的变化,并对界面进行操作,比如模拟点击、滚动、输入等。虽然它最初是为了无障碍辅助设计的需求而创建,但很多辅助工具类应用(如自动跳过广告、自动化脚本、屏幕读取工具等)也会使用它来自动化操作。
AccessibilityService 的功能
1.监听界面事件
AccessibilityService 可以监听各种无障碍事件(AccessibilityEvent),例如:
- 窗口状态变化(TYPE_WINDOW_STATE_CHANGED)
- 视图点击(TYPE_VIEW_CLICKED)
- 文本变化(TYPE_VIEW_TEXT_CHANGED)
- 滑动、长按等操作
2.操作界面控件
通过AccessibilityNodeInfo,服务可以获取界面中的控件信息(如按钮、文本框),并执行操作,例如:
- 模拟点击:node.performAction(AccessibilityNodeInfo.ACTION_CLICK)
- 输入文本:node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT)
- 滑动、滚动等操作。
3.获取界面内容
AccessibilityService 能够获取当前界面所有可见的控件和文本信息,帮助用户完成一些基于界面内容的操作。4.自动化操作
通过监听界面事件并操作控件,AccessibilityService 可以实现自动化功能。例如:
- 自动跳过广告
- 自动填写验证码
- 自动抢红包
- 自动执行一系列预设任务等等
详细代码
public class AutoSkipAdService extends AccessibilityService {
private static final String TAG = "AutoSkipAdService";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event == null || event.getSource() == null) return;
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
if (rootNode != null) {
skipAd(rootNode);
}
}
private void skipAd(AccessibilityNodeInfo node) {
if (node == null) return;
if ((node.getClassName().equals("android.widget.Button") || node.getClassName().equals("android.widget.TextView") || node.getClassName().equals("android.widget.ImageView")) && node.getText() != null && (node.getText().toString().contains("跳过") || node.getText().toString().equalsIgnoreCase("Skip"))) {
performClick(node);
return;
}
// 递归遍历子节点
for (int i = 0; i < node.getChildCount(); i++) {
skipAd(node.getChild(i));
}
}
private void performClick(AccessibilityNodeInfo node) {
while (node != null) {
if (node.isClickable()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
return;
}
node = node.getParent(); // 向上查找父节点
}
}
@Override
public void onInterrupt() {
Log.d(TAG, "服务被中断");
}
}
AndroidManifest.xml 中声明无障碍服务
- android:name:服务类的完整路径,例如 .AutoSkipAdService。
- android:permission:表示这是一个无障碍服务,必须声明 BIND_ACCESSIBILITY_SERVICE 权限。
- android:exported=“true”:表示该服务可以被系统调用。
- < meta-data >指定了无障碍服务的配置文件路径,@xml/accessibility_service_config 是res/xml/accessibility_service_config.xml 文件。
<service
android:name=".AutoSkipAdService"
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_config" />
</service>
无障碍服务配置文件(res/xml/accessibility_service_config.xml)
- android:description:描述无障碍服务的用途,指向 res/values/strings.xml 中的字符串资源。用户在系统的无障碍设置中会看到这个描述。
- android:accessibilityEventTypes:指定服务监听的事件类型
- typeAllMask:监听所有类型的无障碍事件。
- typeWindowStateChanged:窗口状态变化事件。
- typeViewClicked:视图点击事件。
- android:accessibilityFeedbackType:指定反馈类型
- feedbackGeneric:通用反馈类型。
- feedbackSpoken:语音反馈。
- feedbackHaptic:触觉反馈。
- android:accessibilityFlags:指定服务的标志
- flagDefault:默认标志,表示基础功能。
- flagIncludeNotImportantViews:包括不重要的视图(默认不包含不重要的视图)。
- android:notificationTimeout:设置无障碍事件的超时时间,单位为毫秒。
- android:canRetrieveWindowContent:设置为 true 表示服务可以获取窗口内容,这是实现自动跳过广告等功能的关键。
- android:settingsActivity:指定一个设置界面,用户点击无障碍服务时可以跳转到自定义的设置界面(可选)。
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/accessibility_service_description"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:settingsActivity=".AccessibilitySettingsActivity" />
指向 res/values/strings.xml 中的字符串资源
<string name="accessibility_service_description">自动跳过广告服务</string>