記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嗎

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM