zoukankan      html  css  js  c++  java
  • 记AccessibilityService使用(转)

    转自 :http://www.jianshu.com/p/ba298b8d5a6e

     

    一、AccessibilityService的使用

    首先先写一个类去继承AccessibilityService

    public class MyAccessibilityService extends AccessibilityService {
        @Override
        public void onAccessibilityEvent(AccessibilityEvent event) {
            //主要操作都在这里
        }
        @Override
        public void onInterrupt() {  }
    ...
    }

    接下来在res/xml文件夹下新建一个xml文件(不要问我xml文件夹哪来的(:зゝ∠)),叫做aaa.xml(名字随意拉~~)。

    <?xml version="1.0" encoding="utf-8"?>
    <accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
        android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged|typeNotificationStateChanged"
        android:accessibilityFeedbackType="feedbackAllMask"
        android:accessibilityFlags="flagDefault"
        android:canRetrieveWindowContent="true"
        android:description="@string/intro"
        android:notificationTimeout="10"
        android:packageNames="com.tencent.mm"/>

    接下来解释下各个属性:

    • description: 就是给你的这个辅助功能做个简短说明。
    • packageNames: 这个servie希望接收到的事件的包名,如果要接收多个,可以在几个包名之间用 , 隔开。
    • accessibilityEventTypes :这个就是设置了它能监视的动作,比如状态栏来消息拉,界面发生变化拉等等,可以监视一个或多个(由分隔'|')动作,它有typeViewTextChanged,typeNotificationStateChanged,typeWindowContentChanged,typeAllMask等等,其他的类型可以参考这里
    • accessibilityFeedbackType :提供反馈类型,语音震动等等。也是可以设置必一个或多个(由分隔'|')值,可以设置feedbackSpoken、feedbackAllMask等。
    • notificationTimeout:两个相同类型的可访问性事件之间的最小周期。就是监视到一个动作和监视到下一个动作的时间间隔。
    • canRetrieveWindowContent:是否要能够检索活动窗口的内容,此设置不能在运行时改变。
    • settingsActivity:允许用户修改设置该服务的组件名称。

    aaa.xml文件写好以后,就开始配置AndroidManifest.xml文件了

    <service
            android:name=".MyAccessibilityService"
            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/aaa"/>
       </service>

    记住一定还要加上权限

    <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />

    好了,现在所有的东西都以及准备好了,运行程序,就可以在手机的设置-辅助功能里面找到自己的功能了。

    二、抢红包功能

    首先先了解下这个servie响应的事件类型,TYPE_NOTIFICATION_STATE_CHANGED是通知栏事件,TYPE_WINDOW_STATE_CHANGED是窗口状态改变,TYPE_WINDOW_CONTENT_CHANGED是窗口内容改变,这3个就是本次最主要的事件类型,通过AccessibilityEvent可以获得这个事件类型,我们需要做判断即可。

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        switch (eventType) {
            case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
                //TODO处理通知栏来的事件类型
                break;
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                //TODO
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
                //TODO窗口出现变化的时候处理
                break;
        }
    }

    接下来先处理通知栏


    接收到状态栏的消息.png

    从上图可以看到它的event type以及本次抢红包的关键字“[微信红包]”,所以在处理通知栏事件的时候先判断该消息的text是否有关键字,如果有,则打开微信界面。

    private void getNotificationInfo(AccessibilityEvent event) {
        Parcelable parcelable = event.getParcelableData();
        if (parcelable instanceof Notification) {
            Notification notification = (Notification) parcelable;
            try {
                notification.contentIntent.send();
            } catch (PendingIntent.CanceledException e) {
                e.printStackTrace();
            }
        }
    }

    打开界面也就意味这窗口发生改变了,所以onAccessibilityEvent又接收到新的事件了。接下来就要在另外两个事件里面做找红包和开红包的操作了。


    打开红包.png

    红包详情”.png

    从上面两个图片可以知道,点击抢红包和点击开的时候它们的event type都是TYPE_WINDOW_STATE_CHANGED,并且在重点关注一下它们的class,所以可以在TYPE_WINDOW_STATE_CHANGED里面做获取event.getClassName();然后再根据这个class判断到底是做抢红包呢还是开红包呢。

    case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
                rootNodeInfo = getRootInActiveWindow();//相当于获得了这个界面,可以在这上面找控件啊什么的
                if (rootNodeInfo == null) return;
                if (className.equals(com.tencent.mm.ui.LauncherUI)) {
                    getLuckyMoney();//找红包,找到红包就打开
                } else if (className.equals(com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI)) {
                    openLuckyMoney();//开红包
                    backLuckyMoney(eventType);//红包详情,红包抢光了,红包超时了做一个取消的动作
                } else if (className.equals(com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI)) {
                    backLuckyMoney(eventType);
                }
    
                break;

    红包的界面布局.png

    找红包就是在rootNodeInfo里面findAccessibilityNodeInfosByText("领取红包"),如果有,则返回这个红包的AccessibilityNodeInfo。对于图片里面的textview:领取红包,为了反正在聊天界面不停的找到这个开过的红包,然后打开红包,关闭,打开,关闭的死循环,在找红包这边需要加一个判断,如果这个红包已经开过一次了,在窗口没有变化的时候将不点击红包。判断的条件就是图片中的textview:时间和imageview:XXX头像。

    public boolean judgeNode(AccessibilityNodeInfo node) {
        try {
            if (node == null) return false;
    
            AccessibilityNodeInfo node1 = node.getParent().getParent();
    
            int count = node1.getChildCount();
            result.setLength(0);
            for (int i = 0; i < count; i++) {
                AccessibilityNodeInfo node2 = node1.getChild(i);
                if ("android.widget.ImageView".equals(node2.getClassName())) {
                    CharSequence contentDescription = node2.getContentDescription();
                    if (contentDescription != null)
                        result.append(contentDescription.toString());
                }
                if ("android.widget.TextView".equals(node2.getClassName())) {
                    CharSequence thisNodeText = node2.getText();
                    if (thisNodeText != null) result.append(thisNodeText.toString());
                }
            }
            if (result.equals(info)) return false;
            info = hongbaoInfo;
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    红包找到了别忘了在判断结束后加上node.performAction(AccessibilityNodeInfo.ACTION_CLICK)来打开抢红包界面。下面就是开红包了,需要找到红包界面中中间的那个“开”字,有两种办法获得这个字,第一种是递归寻找界面上面的button,它是该界面的唯一button,第二种就是直接使用这个button的resource-id,不过据说这个id腾X会经常改动它,不怕麻烦可以选择哦。


    抢红包的界面布局.png

    找到之后别忘了点击这个node哦node.performAction(AccessibilityNodeInfo.ACTION_CLICK)

    在打开红包后进入红包详情,这时候要退出这个界面回到聊天界面,还有就是红包被抢光了,也需要回到聊天界面,这时候分别判断rootNodeInfo.findAccessibilityNodeInfosByText(text),如果找到,则为true,做performGlobalAction(GLOBAL_ACTION_BACK);就可以了。

    具体的操作全部记录完毕了,目前的代码还有些碧油鸡,还需要改改,先这样吧。

    参考资料:

    自动抢红包,自动安装原理之AccessibilityService
    你真的理解AccessibilityService吗

  • 相关阅读:
    NOIP 2016 回文日期
    USACO Ski Course Design
    USACO Combination Lock
    USACO 利润Profits
    POJ 3368 Frequent values
    USACO Balanced Lineup
    JDOJ 1065 打倒苏联修正主义
    JDOJ 2174 忠诚
    VIJOS-P1514 天才的记忆
    VIJOS-P1423 最佳路线
  • 原文地址:https://www.cnblogs.com/fengchuxiaodai/p/7531163.html
Copyright © 2011-2022 走看看