AccessibilityService简介

版权声明:本文为博主原创文章,未经博主允许不得转载。技术交流可邮:[email protected] https://blog.csdn.net/cjh94520/article/details/50328927

目录

[TOC]来生成目录:

简介

AccessibilityService是一个辅助类,可以监听我们手机的焦点,窗口变化,按钮点击等等。实现它的服务需要在手机设置里面->辅助功能在这里面找到你自己实现的辅助类,然后打开它就可以进行我们一系列的监听了。还可以对监听的对象进行一些脚本的操作。


配置

Manifest.xml配置

新建一个类继承AccessibilityService,并在AndroidManifest文件里注册它,加入对应的Intent-filter,表明是一个辅助服务,同时加入相应的权限.

<application>
  <service android:name=".MyAccessibilityService"
      android:label="@string/accessibility_service_label">
    <intent-filter>
      <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
  </service>
  <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
</application>

配置辅助服务

在代码中配置

一般在onServiceConnected()方法里进行

    private void setServiceInfo(int feedbackType) {
        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        // We are interested in all types of accessibility events.
        info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
        // We want to provide specific type of feedback.
        info.feedbackType = feedbackType;
        // We want to receive events in a certain interval.
        info.notificationTimeout = EVENT_NOTIFICATION_TIMEOUT_MILLIS;
        // We want to receive accessibility events only from certain packages.
        info.packageNames = PACKAGE_NAMES;
        setServiceInfo(info);
    }

在xml文件中配置

从Android4.0开始,开发者可以通过在AndroidManifest里添加标签

<service android:name=".MyAccessibilityService">
  ...
  <meta-data
    android:name="android.accessibilityservice"
    android:resource="@xml/accessibility_service_config" />
</service>
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeNotificationStateChanged
                                      |typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="@string/desc"
    android:notificationTimeout="100" />

配置实现类

子类MyAccessibilityService继承AccessibilityService,并实现相应的重载方法:

方法 描述
onServiceConnected() 可选。系统会在成功连接上你的服务的时候调用这个方法,在这个方法里你可以做一下初始化工作,例如设备的声音震动管理,也可以调用setServiceInfo()进行配置工作
onAccessibilityEvent() 通过这个函数可以接收系统发送来的AccessibilityEvent,接收来的AccessibilityEvent是经过过滤的,过滤是在配置工作时设置的。
onInterrupt() 必须。这个在系统想要中断AccessibilityService返给的响应时会调用。在整个生命周期里会被调用多次。
onUnbind() 可选。在系统将要关闭这个AccessibilityService会被调用。在这个方法中进行一些释放资源的工作

实操

onAccessibilityEvent()中对事件进行监听筛选

    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        switch (eventType) {
            case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:  //收到通知栏消息
                break;
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:    //界面状态改变
                break;
            case  AccessibilityEvent.TYPE_VIEW_CLICKED:   //点击事件
                break;
            case AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT: //文本改变
                break;
            //省略其他的一堆可以监听的事件
        }

    }

获取当前界面各种资源,信息

        //获取根节点
        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        //匹配Text获取节点
        List<AccessibilityNodeInfo> list1 = rootNode.findAccessibilityNodeInfosByText("match_text");
        //匹配id获取节点
        List<AccessibilityNodeInfo> list2 = rootNode.findAccessibilityNodeInfosByViewId("match_id");
        //获取子节点
        AccessibilityNodeInfo infoNode = rootNode.getChild(index);

执行脚本操作

                //模拟点击事件
                target.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                //模拟输入内容
                clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
                ClipData clip = ClipData.newPlainText("label", "");
                clipboard.setPrimaryClip(clip);
                target.performAction(AccessibilityNodeInfo.ACTION_PASTE);

模拟Home,Back键

        //后退键
        performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
        //Home键
        performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);
        //模拟左滑
        performGlobalAction(AccessibilityService.GESTURE_SWIPE_LEFT);

抢红包思路

1.监听微信应用发出的Notification,检查字段是否有“微信红包”字段;

2.点击Notification,进入微信界面

3.调用getRootInActiveWindow()获取根节点;

4.调用findAccessibilityNodeInfosByText(“领取红包”),获取该节点

5.调用performAction(AccessibilityNodeInfo.ACTION_CLICK)实现模拟点击

坑点

1.包被混淆,之前通过Android Device Monitor查看ID,然后根据findAccessibilityNodeInfosByID()去匹配节点,包被混淆之后每个版本不一样

2.很难找出没有文本的控件,如EditText,ImageView

    private void findEditText(AccessibilityNodeInfo root) {
        if (root.getClassName().equals("android.widget.EditText")) {
            target = root;
        } else {
            for (int i = 0; i < root.getChildCount(); i++) {
                if (root.getChildCount() != 0) {
                    findEditText(root.getChild(i));
                }
            }
        }
    }

3.锁屏抢红包要解除锁屏,isKeyguardLocked()方法错误理解。刚开始写代码的时候默认检测是否有锁屏,如果锁屏了调用disableKeyguard(),解锁,然后再检测是否真正解锁,成功解锁之后再进行抢红包的逻辑。后面发现disableKeyguard()并不是真正能够解锁,只是隐藏了锁屏。

km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
                            //得到锁管理器对象
                            boolean flag = km.isKeyguardLocked();
                            isFromNotification = true;
                            if (flag == true) {
                                kl = km.newKeyguardLock("unLock");
                                kl.disableKeyguard();
                            }
                                gotoWeCharUI(event);

官方对disableKeyguard()解释:
* Disable the keyguard from showing. If the keyguard is currently
* showing, hide it. The keyguard will be prevented from showing again
* until {@link #reenableKeyguard()} is called.

猜你喜欢

转载自blog.csdn.net/cjh94520/article/details/50328927