Android AccessibilityService机制源码解析

本文深入解析Android AccessibilityService机制,解答如何监控用户行为、查找控件及执行操作。通过创建AccessibilityService,分析源码,揭示其内部逻辑,包括事件处理、控件查找和交互过程。适合希望了解Android辅助服务实现原理的开发者。
摘要由CSDN通过智能技术生成
一、本文需要解决的问题

之前本人做了一个项目,需要用到AccessibilityService这个系统提供的拓展服务。这个服务本意是作为Android系统的一个辅助功能,去帮助残疾人更好地使用手机。但是由于它的一些特性,给很多项目的实现提供了一个新的思路,例如之前大名鼎鼎的微信抢红包插件,本质上就是使用了这个服务。我研究AccessibilityService的目的是解决以下几个我在使用过程中所思考的问题:
1. AccessibilityService这个Service跟一般的Service有什么区别?
2. AccessibilityService是如何做到监控并捕捉用户行为的?
3. AccessibilityService是如何做到查找控件,执行点击等操作的?

二、初步分析

本文基于Android 7.1的源码对AccessibilityService进行分析。
为了更好地理解和分析代码,我写了一个demo,如果想学习具体的使用方法,可以参考Google官方文档AccessibilityService。本文不做AccessibilityService的具体使用教程。

创建AccessibilityService
public class MyAccessibilityService extends AccessibilityService {
   

    private static final String TAG = "MyAccessibilityService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate");
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        switch (eventType) {
            case AccessibilityEvent.TYPE_VIEW_CLICKED:
                // 捕获到点击事件
                Log.i(TAG, "capture click event!");
                AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
                if (nodeInfo != null) {
                    // 查找text为Test!的控件
                    List<AccessibilityNodeInfo> button = nodeInfo.findAccessibilityNodeInfosByText("Test!");
                    nodeInfo.recycle();
                    for (AccessibilityNodeInfo item : button) {
                        Log.i(TAG, "long-click button!");
                        // 执行长按操作
                        item.performAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
                    }
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void onInterrupt() {
        Log.i(TAG, "onInterrupt");
    }
}
AccessibilityService配置

res/xml/accessibility_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="feedbackSpoken"
    android:accessibilityFlags="flagRetrieveInteractiveWindows|flagRequestFilterKeyEvents"
    android:canRequestFilterKeyEvents="true"
    android:canRetrieveWindowContent="true"
    android:description="@string/app_name"
    android:notificationTimeout="100"
    android:packageNames="com.xu.accessibilitydemo" />
在manifest中进行注册
<service
    android:name=".MyAccessibilityService"
    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_config"/>
</service>
创建一个text为Test!的button控件,设置监听方法
public class MainActivity extends AppCompatActivity {
   

    private static final String TAG = "MainActivity";

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = findViewById(R.id.button);

        button.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Log.i(TAG, "onLongClick");
                return false;
            }
        });

    }
}
开启AccessibilityService

AccessibilityService服务开启位置在设置–无障碍中。

运行应用,点击text为Test!的按钮

会出现以下的日志:
log.png

具体解释:
点击按钮即产生TYPE_VIEW_CLICKED事件 –> 被AcceesibilityService捕获 –> 捕获后执行长按按钮操作 –> 执行长按回调方法。

为什么AcceesibilityService能捕获并执行其他操作呢,接下来我将对源码进行解析~

三、源码解析
AccessibilityService内部逻辑
AccessibilityService.java
public abstract class AccessibilityService extends Service {
   
      // 省略代码
      public abstract void onAccessibilityEvent(AccessibilityEvent event);

      public abstract void onInterrupt();

      @Override
      public final IBinder onBind(Intent intent) {
          return new IAccessibilityServiceClientWrapper(this, getMainLooper(), new Callbacks() {
              @Override
              public void onServiceConnected() {
                  AccessibilityService.this.dispatchServiceConnected();
              }

              @Override
              public void onInterrupt() {
                  AccessibilityService.this.onInterrupt();
              }

              @Override
              public void onAccessibilityEvent(AccessibilityEvent event) {
              
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值