1. 程式人生 > >Android微信/QQ紅包自動搶(AccessibilityService)

Android微信/QQ紅包自動搶(AccessibilityService)

關於搶紅包的文章已經很多了,我再來總結下,QQ的順便也實現下,原理很簡單,搜尋螢幕中的文字,搜尋到了就點選,QQ相對來說要簡單一些

關鍵程式碼:

AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
nodeInfo.findAccessibilityNodeInfosByText("恭喜");

首先,在輔助功能裡面開啟服務後,onAccessibilityEvent方法會接受到一些事件,我們來看看常用的一些事件

public class Types{
    final class types {
        //所有事件
public static final int types_all_mask = -1; //通知欄 public static final int type_notification_state_changed = 64; //點選事件 public static final int type_view_clicked = 1; //控制元件獲取焦點 public static final int type_view_focused = 8; //長按事件 public
static final int type_view_long_clicked = 2; //頁面變動 public static final int type_view_scrolled = 4096; //控制元件選中 public static final int type_view_selected = 4; //輸入框文字改變 public static final int type_view_text_changed = 16; //輸入框文字selection改變 public
static final int type_view_text_selection_changed = 8192; //視窗內容改變 public static final int type_window_content_changed = 2048; //視窗狀態改變 public static final int type_window_state_changed = 32; } }
typeAllMask代表可以監聽到所有的事件,我們這次只用到typeNotificationStateChanged和typeWindowStateChanged,還有typeWindowContentChanged

下面開始具體程式碼

1、建立Service

WXEnvelopeService.java

package com.zx.redenvelopes;

import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Instrumentation;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static android.content.ContentValues.TAG;

//文字型別:
// 微信text==童鞋: 恭喜發財

//紅包型別:
// 微信text==童鞋: [微信紅包]恭喜發財,大吉大利

public class WXEnvelopeService extends AccessibilityService {


    static final String ENVELOPE_TEXT_KEY = "[微信紅包]";


    @SuppressLint("NewApi")
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        final int eventType = event.getEventType();

        //Log.d(TAG, "微信事件--------------------------" + event.getEventType());

        //通知欄事件
        if (eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
            List<CharSequence> texts = event.getText();
            if (!texts.isEmpty()) {
                for (CharSequence t : texts) {
                    String text = String.valueOf(t);
                    Log.v("tag", "監控微信訊息==" + text);
                    if (text.contains(ENVELOPE_TEXT_KEY)) {
                        openNotification(event);
                        break;
                    }
                }
            }
        } else if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            openEnvelope(event);
        } else if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
            openEnvelopeContent(event);
        }
    }

    /**
     * 開啟通知欄訊息並跳轉到紅包頁面
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void openNotification(AccessibilityEvent event) {
        if (event.getParcelableData() == null || !(event.getParcelableData() instanceof Notification)) {
            return;
        }
        //以下是精華,將微信的通知欄訊息開啟
        Notification notification = (Notification) event.getParcelableData();
        PendingIntent pendingIntent = notification.contentIntent;
        try {
            pendingIntent.send();
        } catch (PendingIntent.CanceledException e) {
            e.printStackTrace();
        }
    }


    @TargetApi(Build.VERSION_CODES.KITKAT)
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void openEnvelope(AccessibilityEvent event) {

        if ("com.tencent.mm.ui.LauncherUI".equals(event.getClassName())) {
            checkKeyFirst();
        } else if ("com.tencent.mm.plugin.luckymoney.ui.En_fba4b94f".equals(event.getClassName())) {
            checkOpen();
        } else if ("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI".equals(event.getClassName())) {

            //Toast.makeText(this, "紅包已經搶完--------", Toast.LENGTH_SHORT).show();
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void openEnvelopeContent(AccessibilityEvent event) {

        if ("android.widget.TextView".equals(event.getClassName())) {
            checkKeyFirst();
        } else if ("com.tencent.mm.plugin.luckymoney.ui.En_fba4b94f".equals(event.getClassName())) {
            checkOpen();
        } else if ("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI".equals(event.getClassName())) {
            // Toast.makeText(this, "紅包已經搶完--------", Toast.LENGTH_SHORT).show();

        }
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void checkOpen() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            return;
        }
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("恭喜");
        for (int i = list.size() - 1; i >= 0; i--) {

            AccessibilityNodeInfo parent = list.get(i).getParent();
            for (int j = 0; j < parent.getChildCount(); j++) {
                AccessibilityNodeInfo child = parent.getChild(j);
                if (child != null && child.isClickable()) {
                    child.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    break;
                }
            }

        }
    }

    private void checkKeyFirst() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            return;
        }
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("領取紅包");
        if (list.isEmpty()) {
            return;
        }
        for (int i = list.size() - 1; i >= 0; i--) {
            AccessibilityNodeInfo parent = list.get(i).getParent();
            if (parent != null) {
                parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
        }
    }


    @Override
    public void onInterrupt() {
        Toast.makeText(this, "微信搶紅包服務已關閉", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Toast.makeText(this, "微信搶紅包服務已開啟", Toast.LENGTH_SHORT).show();
    }

}

QQEnvelopeService.java

package com.zx.redenvelopes;

import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import java.util.List;

import static android.content.ContentValues.TAG;

//文字型別:
// 監控QQ訊息==童鞋: 恭喜發財

//紅包型別:
// 監控QQ訊息==童鞋: [QQ紅包]恭喜發財

public class QQEnvelopeService extends AccessibilityService {

    static final String ENVELOPE_TEXT_KEY = "[QQ紅包]";


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        Log.d(TAG, "QQ事件--------------------------" + event.getEventType());

        final int eventType = event.getEventType();

        if (eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
            List<CharSequence> texts = event.getText();
            if (!texts.isEmpty()) {
                for (CharSequence t : texts) {
                    String text = String.valueOf(t);
                    Log.v("tag", "監控QQ訊息==" + text);
                    if (text.contains(ENVELOPE_TEXT_KEY)) {
                        openNotification(event);
                        break;
                    }
                }
            }
        } else if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            openEnvelope(event);
        } else if(eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
            openEnvelopeContent(event);

        }
    }

    /**
     * 開啟通知欄訊息並跳轉到紅包頁面
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void openNotification(AccessibilityEvent event) {
        if (event.getParcelableData() == null || !(event.getParcelableData() instanceof Notification)) {
            return;
        }
        //以下是精華,將微信的通知欄訊息開啟
        Notification notification = (Notification) event.getParcelableData();
        PendingIntent pendingIntent = notification.contentIntent;
        try {
            pendingIntent.send();
        } catch (PendingIntent.CanceledException e) {
            e.printStackTrace();
        }
    }




    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void openEnvelope(AccessibilityEvent event) {
        if ("com.tencent.mobileqq.activity.SplashActivity".equals(event.getClassName())) {
            checkKey();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void openEnvelopeContent(AccessibilityEvent event) {
        /*if ("android.widget.RelativeLayout".equals(event.getClassName())) {
            checkKey();
        } else if("android.widget.TextView".equals(event.getClassName())) {
            checkKey();
        }*/
        checkKey();
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void checkKey() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            return;
        }
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("點選拆開");
        if (list.isEmpty()) {
            return;
        }
        for (AccessibilityNodeInfo info : list) {
            AccessibilityNodeInfo parent = info.getParent();
            if (parent != null) {
                parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
        }
    }

    @Override
    public void onInterrupt() {
        Toast.makeText(this, "QQ搶紅包服務已關閉", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Toast.makeText(this, "QQ搶紅包服務已開啟", Toast.LENGTH_SHORT).show();
    }

}

2、建立對應的xml

res/xml/envelope_service_config_qq.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 關鍵是android:accessibilityEventTypes="typeAllMask", typeAllMask代表監聽所有的事件,這邊不寫的話,AccessibilityService就接收不到 -->
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagRequestFilterKeyEvents"
    android:canRetrieveWindowContent="true"
    android:canRequestFilterKeyEvents="true"
    android:description="@string/accessibility_description"
    android:notificationTimeout="100"
    android:packageNames="com.tencent.mobileqq" />

res/xml/envelope_service_config_wx.xml

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

3、AndroidManifest.xml中註冊

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.zx.redenvelopes">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_app"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <service
            android:enabled="true"
            android:exported="true"
            android:label="QQ自動搶紅包服務"
            android:name=".QQEnvelopeService"
            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/envelope_service_config_qq"/>
        </service>
        <service
            android:enabled="true"
            android:exported="true"
            android:label="微信自動搶紅包服務"
            android:name=".WXEnvelopeService"
            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/envelope_service_config_wx"/>
        </service>
    </application>

</manifest>

最後開啟服務的程式碼如下:

//開啟系統設定中輔助功能
Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
                startActivity(intent);
                Toast.makeText(MainActivity.this, "找到微信/QQ自動搶紅包服務,開啟即可", Toast.LENGTH_LONG).show();

相關推薦

Android/QQ紅包自動AccessibilityService

關於搶紅包的文章已經很多了,我再來總結下,QQ的順便也實現下,原理很簡單,搜尋螢幕中的文字,搜尋到了就點選,QQ相對來說要簡單一些 關鍵程式碼: AccessibilityNodeInfo nodeInfo = getRootInActiveWindow

小程式之仿android fragment之可滑動的底部導航欄例項 —— 小程式實戰系列4

底部3-5個選項的底部導航欄,目前在移動端上是主流佈局之一 因此騰訊官方特地做了,可以通過設定,就可以做出了一個底部的導航欄 但是通過設定的這個底部的導航欄,功能上比較固定,它必須要設定與它對應的一個頁面,而且並不能滑動。 在業務上,有時候會比較限制,並不能完全滿足所需

公眾平臺開發者模式2JAVA自動回覆文字訊息及多圖文訊息

資料流向 使用者<———–>微信端 <———–>後臺伺服器 成功接入微信端後 接受微信端傳送的xml訊息,解析為實體物件,處理後再轉成xml格式的資料傳送給微信端 servlet程式碼 public void doPost

Android簡單實現仿選擇圖片以及拍照PhotoPicker

實現仿微信的圖片選擇,預覽以及拍照,屬性可以設定顯示照相機以及預覽時是否顯示刪除按鈕等,功能齊全並且可以根據儲存照片的路徑進行修改等 Gradle配置 dependencies { co

Python-快速實現公眾號自動回覆聊天機器人

原理:通過微信公眾號提供的開發者模式,利用Python搭建環境,實現自動回覆,回覆內容通過呼叫圖靈機器人的API 配置:伺服器(這裡是阿里雲主機,Ubuntu),公眾號,圖靈機器人 一,公眾平臺上進行開發配置 三種加密方式,按需選擇。第一種最簡單,最不安全(我這裡選擇的第

小程序 支付功能前端的實現

pen 回退 ole pack spa session 統一支付 ges 應用 只提供微信小程序端代碼: 1 var app = getApp(); 2 Page({ 3 data: {}, 4 onLoad: function (options) {

小程序訪問webServiceJava

微信小程序解析xml 微信小程序調用java(wsdl) 在前臺UI確認後,終於進入到後臺服務的搭建及實現中。所及而來的問題就出現了,為了提高後臺程序的可用性。設計初期決定,通過搭建java WebService實現。準備工作還是比較充分的,創建WebService框架,實現接口方法。通過建立測試客戶端

小程序開發教程視圖層——.wxml詳解

span hid 處理 路徑 strong 一般來說 emp 條件 頁面數據   框架的視圖層由WXMKL(WeiXin Markup language)與WXSS(WeiXin Style Sheet)編寫,由組件進行展示。   對於微信小程序而言,視圖層就是所有.wxm

小程序開發教程視圖層——.wxss詳解

hone mnt 而且 padding 移動 圖層 組成 特性 -1   WXSS是一套樣式語言,用於描述WXML的組件樣式。   官方文檔表示,WXSS的選擇器目前支持(“.class”、“#id”、“elemnt”、“element,element”、“::after”

公眾平臺開發教程 基礎框架搭建

開發 images wxs user 設計實現 bytes trre 來源 app 上一章,我們已經初步講解了微信公眾賬號開發的基本原理,今天我們來探索設計實現。 首先我們設計了模塊層次圖,當然圖中只是給出一種實現方式,不局限於此。具體見下圖。 主要功能介紹如下: 1)請求

公眾平臺開發教程 公眾賬號註冊流程

身份證 logs 政府 提交 註意 bsp 訪問服務器 定義 htm 具體的操作步驟 1、註冊公眾賬號 註冊地址:http://mp.weixin.qq.com/ 1)首先需要郵箱註冊: 2)郵箱激活。郵箱將會收到激活郵件,點擊激活鏈接即可。 3)需要登記個人信息。這裏需

公眾平臺開發教程Session處理

class 如果 obj returns name ref car opera 信用 在微信窗口,輸入的信息有限,我們需要將一些信息分多次請求。 比如:在進行用戶綁定時,我們需要輸入用戶的相關信息,比如:用戶名、密碼,或者姓名、電話號碼,服務端驗證通過,即可將系統用戶與微信

公眾平臺開發教程 訂閱號與服務號的區別

接口文檔 lpad 手機 全部 oauth2.0 spa 上傳 ima lsp 為了消除大家對訂閱號與服務號的疑問,特總結如下: 功能點 介紹 訂閱號 服務號 註冊 註冊賬號 個人信息 個人信息和企業相關信息 展示 在

公眾平臺開發教程 基本原理及消息接口

username 普通用戶 縮放 地理位置 cfb 位置 註意 獲得 基本 一、基本原理 在開始做之前,大家可能對這個很感興趣,但是又比較茫然。是不是很復雜?很難學啊? 其實恰恰相反,很簡單。為了打消大家的顧慮,先簡單介紹了微信公眾平臺的基本原理。 微信服務器就相當於一個轉

公眾平臺開發教程自定義菜單

打開鏈接 delete toolbar 推送 優化 pcl reader 接口查詢 robot 應大家強烈要求,將自定義菜單功能課程提前。 一、概述: 如果只有輸入框,可能太簡單,感覺像命令行。自定義菜單,給我們提供了很大的靈活性,更符合用戶的操作習慣。在一個小小的微信對話

小程序——豆瓣電影——2:小程序運行部署

images 放心 覆蓋 當前 .cn markup 必須 global 定義 Demo 預覽 演示視頻(流量預警 2.64MB) GitHub Repo 地址 倉庫地址:https://github.com/zce/weapp-demo 使用步驟 將倉庫克隆到本地

[轉]小程序之加載更多分頁加載實例 —— 小程序實戰系列2

是否 底部 watermark water ongl 小程序教程 所有 空數組 osi 本文轉自;http://blog.csdn.net/michael_ouyang/article/details/56846185 loadmore 加載更多(分頁加載) 當

小程序的開發

ram tle ati java ndt 喜歡 top lex navig 我現在在學習,微信小程序開發,剛剛看看一篇對我特別有用的博客文章,我就把摘抄過來了,好好的學習一下。 序言 開始開發應用號之前,先看看官方公布的「小程序」教程吧!(以下內容來自微信官方公布的「小程序

消息加解密GoLang-- 接收和回復加密消息

too simple 更改 chatapp body sge and print news 接收微信消息的接口內容: //"r"為*http.Request r.ParseForm() timestamp := strings.Join(r.For

如何利用Python網絡爬蟲抓取朋友圈的動態

Python 網絡爬蟲 微信 朋友圈 Python開發 今天小編給大家分享一下如何利用Python網絡爬蟲抓取微信朋友圈的動態信息,實際上如果單獨的去爬取朋友圈的話,難度會非常大,因為微信沒有提供向網易雲音樂這樣的API接口,所以很容易找不到門。不過不要慌,小編在網上找到了第三方工具,它可