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();

http://blog.csdn.net/jiangwei0910410003/article/details/48895153
http://blog.csdn.net/qq_30379689/article/details/53242953

源码下载:
http://download.csdn.net/download/zx_android/10213833

发布了55 篇原创文章 · 获赞 93 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/zx_android/article/details/78706615