天天看點

Android微信搶紅包功能的實作

快到過農曆年了,微信紅包也越來越多了,出現了好多紅包外挂程式,就很好奇如何實作的,于是自己研究了一番,親自寫了個微信搶紅包的APP。現在就一步一步來實作它。

實作思路

微信搶紅包程式開啟時候,他就可以随時識别、捕獲紅包,服務可以實作正在功能,當我們開啟服務的時候,服務就不停的在背景運作,不停地輪詢着微信裡面的消息,當發現紅包時候就立即打開微信紅包所在的界面。但是他怎識别紅包呢?需要找到微信搶紅包裡面節點的view,當找到對應的view,在擷取view的關鍵字或者id,根據關鍵字或者id,自動的模拟點選,拆開紅包。這裡有一個AccessibilityService的服務,他是一個輔助類,可以實作這些功能。

AccessibilityService輔助類

AccessibilityService是一個輔助類,可以監聽我們手機的焦點,視窗變化,按鈕點選,聲音提示等等,但是必須手動開啟,不能通過代碼開啟,存在于設定裡面的輔助功能,開啟他我們可以增強互動性。現在來來使用他實作搶紅包功能:

1、建立一個類QiangHongBaoService繼承自AccessibilityService

@Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        //擷取事件類型
        int type = event.getEventType();
        //在這裡進行事件過濾
        
    }
           

2、注冊清單檔案

<service
            android:name=".QiangHongBaoService"
            android:label="@string/app_name"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter android:priority="1000">
                <action android:name="android.accessibilityservice.AccessibilityService"/>
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/envelope_service_config"/>
        </service>
           

建立一個xml檔案夾,建立envelope_service_config檔案

<?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/accessibility_description"
                       android:notificationTimeout="100"
                       android:packageNames="com.tencent.mm" />
           

記得加上網絡權限:<uses-permission android:name="android.permission.VIBRATE" />

搶紅包業務邏輯處理

在微信搶紅包界面上隻關心兩個事件類型:

1、AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED//監聽通知欄消息

在監聽通知欄消息界面主要是監聽每次微信發過來的消息顯示在通知欄時,擷取消息,當發現擷取的消息含有“微信紅包”時就會立即打開 紅包所顯示的界面。

/**
     * 從知消息欄打開微信聊天界面
     * @param event
     */
    private void openNotification(AccessibilityEvent event) {
        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();
            }
        }
    }
           

2、AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED//目前視窗變化,是否進入微信聊天界面

在這裡需要根據包名判斷是否是聊天界面,如果是則點中紅包,如果不是判斷是否是拆紅包界面,如果是則拆開,執行拆紅包動作。

聊天界面的包名:com.tencent.mm.ui.LauncherUI

拆紅包界面的包名:com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI

/**
     * 點中紅包
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void clickHongBao() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            return;
        }
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(ENVLOP_OPEN_KEY);
        if (list.isEmpty()) {
            list = nodeInfo.findAccessibilityNodeInfosByText(ENVELOPE_TEXT_KEY);
            for (AccessibilityNodeInfo n : list) {
                n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
        } else {
            //最新的紅包領起
            for (int i = list.size() - 1; i >= 0; i--) {
                AccessibilityNodeInfo parent = list.get(i).getParent();
                if (parent != null) {
                    parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    break;
                }
            }
        }
    }
           
/**
     *拆紅包
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void openHongBao() {
        AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow();
        if (rootInActiveWindow == null) {
            return;
        }
        List<AccessibilityNodeInfo> nodeInfos = rootInActiveWindow.findAccessibilityNodeInfosByViewId(ENVLOP_CHECKED_KEY);
        for (AccessibilityNodeInfo nodeInfo : nodeInfos) {
            nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
    }
           

上例中的拆紅包是依據控件的id拆開的,也可以按照關鍵字“拆紅包”執行。但是效率略低于根據id拆紅包,這樣很可能影響搶紅包的效率,需要注意的是拆紅包的id在微信不同版本中是不一樣的,是以需要經常改變,比較麻煩。此外當AccessibilityService服務被關閉時會回調onInterrupt方法,當連接配接上時會回調onServiceConnected方法,在這裡可以做一些提示性的工作。

搶紅包功能的開啟

微信搶紅包功能是通過手動開啟的,直接在設定裡面找到輔助功能,點選開啟,為了友善,給activity設定一個按鈕,采用隐式意圖的方式,直接跳轉至服務功能。

//打開系統設定中輔助功能
Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(intent);
           

到了這裡微信搶紅包的而核心功能介紹完了,搶紅包的效率還受網絡,手機記憶體大小,系統流暢度的影響,以及服務優先級等等因素的影響。這裡隻是學習一下,千萬别用來經常外挂來搶紅包,小心被封号哦!!!

源碼已經上傳至github,需要的點選打開連結

https://github.com/yoonerloop/WebEnvelope