天天看點

插件 微信 自動 搶紅包

  1. 搶紅包插件

先回顧一下搶紅包的的流程:

  1. 狀态欄出現"[微信紅包]"的消息提示,點選進入聊天界面
  2. 點選相應的紅包資訊,彈出搶紅包界面
  3. 在搶紅包界面點選"開",打開紅包
  4. 在紅包詳情頁面,檢視詳情,點選傳回按鈕傳回微信聊天界面.

以上是不在微信聊天界面時的流程.如果你所在的微信聊天視窗出現紅包,則不會執行步驟1,而是直接執行2,3,4.如果是在微信好友清單時,收到紅包,則會在清單項中顯示[微信紅包],需要點即該清單項,進入聊天界面,随後執行2,3,4.為了友善示範,這裡我們暫時不考慮好友清單時出現紅包的情況.

明白了搶紅包流程,之後我們通過AccessibilityService擷取通知欄資訊及微信聊天視窗界面,繼而通過模拟點選實作打開紅包,搶紅包等操作.

AccessibilityService配置如下:

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

具體實作代碼如下:

public class RobService extends AccessibilityService {


    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        switch (eventType) {
            case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
                handleNotification(event);
                break;
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
                String className = event.getClassName().toString();
                if (className.equals("com.tencent.mm.ui.LauncherUI")) {
                    getPacket();
                } else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) {
                    openPacket();
                } else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")) {
                    close();
                }

                break;
        }
    }

    /**
     * 處理通知欄資訊
     *
     * 如果是微信紅包的提示資訊,則模拟點選
     *
     * @param event
     */
    private void handleNotification(AccessibilityEvent event) {
        List<CharSequence> texts = event.getText();
        if (!texts.isEmpty()) {
            for (CharSequence text : texts) {
                String content = text.toString();
                //如果微信紅包的提示資訊,則模拟點選進入相應的聊天視窗
                if (content.contains("[微信紅包]")) {
                    if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
                        Notification notification = (Notification) event.getParcelableData();
                        PendingIntent pendingIntent = notification.contentIntent;
                        try {
                            pendingIntent.send();
                        } catch (PendingIntent.CanceledException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    /**
     * 關閉紅包詳情界面,實作自動傳回聊天視窗
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void close() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo != null) {
            //為了示範,直接檢視了關閉按鈕的id
            List<AccessibilityNodeInfo> infos = nodeInfo.findAccessibilityNodeInfosByViewId("@id/ez");
            nodeInfo.recycle();
            for (AccessibilityNodeInfo item : infos) {
                item.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }
    }

    /**
     * 模拟點選,拆開紅包
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void openPacket() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo != null) {
            //為了示範,直接檢視了紅包控件的id
            List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("@id/b9m");
            nodeInfo.recycle();
            for (AccessibilityNodeInfo item : list) {
                item.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }
    }

    /**
     * 模拟點選,打開搶紅包界面
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void getPacket() {
        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        AccessibilityNodeInfo node = recycle(rootNode);

        node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        AccessibilityNodeInfo parent = node.getParent();
        while (parent != null) {
            if (parent.isClickable()) {
                parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
            parent = parent.getParent();
        }

    }

    /**
     * 遞歸查找目前聊天視窗中的紅包資訊
     *
     * 聊天視窗中的紅包都存在"領取紅包"一詞,是以可根據該詞查找紅包
     * 
     * @param node
     */
    public AccessibilityNodeInfo recycle(AccessibilityNodeInfo node) {
        if (node.getChildCount() == 0) {
            if (node.getText() != null) {
                if ("領取紅包".equals(node.getText().toString())) {
                    return node;
                }
            }
        } else {
            for (int i = 0; i < node.getChildCount(); i++) {
                if (node.getChild(i) != null) {
                    recycle(node.getChild(i));
                }
            }
        }
        return node;
    }

    @Override
    public void onInterrupt() {

    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
    }


}


           

上面的代碼簡單示範了搶紅包的原理,為了友善起見,我直接通過

findAccessibilityNodeInfosByViewId()

擷取制定id控件.在實際中,這種方法不太可靠,到目前為止,微信已經改過幾次相關控件的id了.

有童鞋問,怎麼樣知道該控件的id呢.其實很簡單,android中已經為我們提供了相關的工具:在Android Studio中開啟Android Device Monitor,選擇裝置後點選Dump View Hierarchy for UI Automator,如下:

插件 微信 自動 搶紅包

這裡寫圖檔描述

稍等片刻之後,便會出現目前裝置的視窗,在該視窗中點選相關控件,便會顯示該控件的屬性.借助該工具,可以幫我們快速的分析界面結構,幫助我們從其他app布局政策中學習

插件 微信 自動 搶紅包

這裡寫圖檔描述

我們用Dump View Hierarchy for UI Automator分析聊天界面微信紅包資訊:

插件 微信 自動 搶紅包

這裡寫圖檔描述

搶紅包界面:

插件 微信 自動 搶紅包

這裡寫圖檔描述

插件 微信 自動 搶紅包