Android 微信自动抢红包(源码以及apk下载可以参考末文)

一、调试环境搭建:

基础调试环境可以用手机真机,shell权限即可或者android 模拟器,推荐无广告,并且android高版本支持的genymotion (模拟器有root权限),可以在官网自行下载注册用于学习:https://www.genymotion.com/,由于是X86架构,需要自己下载X86兼容arm的依赖包Genymotion-ARM-Translation:https://github.com/m9rco/Genymotion_ARM_Translation,

在这里插入图片描述
然后下载一个android 8.0的版本启动模拟器就可以开始基础调试了;我们不用hook的方法,在高版本Android机型可以用Android AccessibilityService(无障碍服务)来实现微信自动抢红包;夜神模拟器等商用模拟器android版本更新太慢,很多机型适配可能存在不少问题,开发实用性不够;

二、具体代码实现可以参考:https://github.com/xiaxiaxa/RedWechat (近期整理并且debug的一个基础版本)

1、在AndroidManifest.xml中注册服务MyAccessibilityService,具体可以参考官方文档

像其他Service服务一样,需要在AndroidManifest.xml中声明该服务,还必须配置以下两项:
a:配置,其name为固定的:android.accessibilityservice.AccessibilityService;
b:声明BIND_ACCESSIBILITY_SERVICE权限,以便系统能够绑定该服务(4.0版本后要求);

注意:任何一点配置错误,系统都无反应,因此其固定配置如下

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:canPerformGestures="true"
    android:theme="@style/AppTheme">

    <activity android:name="com.example.redwechat.QHBActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <service
        android:name="com.example.redwechat.MyAccessibilityService"
        android:enabled="true"
        android:exported="true"
        android:label="@string/label"
        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/accessibility_service_config" />
    </service>    
</application>

AccessbilityService的生命周期由系统管理,遵循Service的基本生命周期,只能由用户自己在设置中手动启动,系统绑定到服务后,会调用它的onServiceConnected()方法。当用户手动在设置中关闭服务,或者开发者调用disableSelf()方法时,该服务会被关闭销毁。

2、具体自动抢红包的实现基本上在自定义服务MyAccessibilityService里面实现MyAccessibilityService继承AccessbilityService;我们可以看看AccessibilityService类中具体有哪些方法:

方法作用
disableSelf()禁用当前服务,也就是在服务可以通过该方法停止运行
findFoucs(int falg)查找拥有特定焦点类型的控件
getRootInActiveWindow()如果配置能够获取窗口内容,则会返回当前活动窗口的根结点
getSeviceInfo()获取当前服务的配置信息
onAccessibilityEvent(AccessibilityEvent event)有关AccessibilityEvent事件的回调函数.系统通过sendAccessibiliyEvent()不断的发送AccessibilityEvent到此处
performGlobalAction(int action)执行全局操作,比如返回,回到主页,打开最近等操作
setServiceInfo(AccessibilityServiceInfo info)设置当前服务的配置信息
getSystemService(String name)获取系统服务
onKeyEvent(KeyEvent event)如果允许服务监听按键操作,该方法是按键事件的回调,需要注意,这个过程发生了系统处理按键事件之前
onServiceConnected()系统成功绑定该服务时被触发,也就是当你在设置中开启相应的服务,系统成功的绑定了该服务时会触发,通常我们可以在这里做一些初始化操作

AccessibilityEvent中,几种常用的:

类型作用注释
TYPE_WINDOW_STATE_CHANGED页面状态发生变化对于activity页面onResume就会调用一次, 弹出dialog,popwindow,menu,也都会监听
TYPE_WINDOW_STATE_CHANGED页面有内容发生改变比如添加或者删除一个view,checkbox选中变成非选中,一个textview的内容变化了等等
TYPE_VIEW_CLICKEDD当View被点击时发送此事件
TYPE_VIEW_LONG_CLICKED当View被长按时发送此事件
TYPE_VIEW_FOCUSED当View获取到焦点时发送此事件
TYPE_NOTIFICATION_STATE_CHANGED判断辅助服务触发的事件是否是通知栏改变事件

基础功能code主要实现在TYPE_WINDOW_CONTENT_CHANGED事件跟TYPE_WINDOW_STATE_CHANGED事件

打开微信聊天收到红包或者在聊天页面收到信息更新收到红包的情况;

        case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
        case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
            String className = event.getClassName().toString();
            AccessibilityNodeInfo rootNode = getRootInActiveWindow();
            if (WECHAT_UI.equals(className) || WECHAT_UI_2.equals(className)) {
                findRedPacket(rootNode);
            }
            if (WECHAT_RED.equals(className)) {
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        openRedPacket();
                        isOpenDetail = true;
                    }
                }, DELAY_TIME);

            }
            if (isOpenDetail && WECHAT_RED_DETAIL.equals(className)) {
                isOpenDetail = false;
                release();
            }
            break;
    }

这里就要讲到微信的几个对应的布局界面:

布局界面名称
微信聊天界面com.tencent.mm.ui.LauncherUI
弹出拆红包的界面com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyNotHookReceiveUI
拆开红包后的详情页com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI
对应的红包拆字按钮android.widget.Button

3、详细实现:

在聊天界面有信息内容更新或者聊天界面状态发生变化的时候,我们需要遍历查找红包;如何查询呢?从当前页面布局的最后一行开始,判断是否已经打开过那个最新的红包了,是的话就跳出for循环,不是的话继续遍历;

/**
 * 遍历查找红包
 */
private void findRedPacket(AccessibilityNodeInfo accessibilityNodeInfo) {
    if (accessibilityNodeInfo != null) {
        for (int i = accessibilityNodeInfo.getChildCount() - 1; i >= 0; i--) {
            AccessibilityNodeInfo accessibilityNodeInfoChild = accessibilityNodeInfo.getChild(i);
            if (accessibilityNodeInfoChild == null) {
                continue;
            }
            CharSequence text = accessibilityNodeInfoChild.getText();
            if (text != null && text.toString().equals(WECHAT_RED_NAME)) {
                AccessibilityNodeInfo parent = accessibilityNodeInfoChild.getParent();
                while (parent != null) {
                    if (parent.isClickable()) {
                        if (!parent.getChild(1).getText().equals(IS_GET_WECHAT_RED_NAME) &&
                                !parent.getChild(1).getText().equals(IS_ALL_GET_WECHAT_RED_NAME)) {
                            parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                            isOpenRP = true;
                        }
                        break;
                    }
                    parent = parent.getParent();
                }
            }
            findRedPacket(accessibilityNodeInfoChild);
            if (isOpenRP) {
                break;
            } else {
                findRedPacket(accessibilityNodeInfoChild);
            }

        }
    }
}

** 找到红包后,拆开红包:**

/**
 * 开始打开红包
 */
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void openRedPacket() {
    AccessibilityNodeInfo rootNode = getRootInActiveWindow();
    for (int i = 0; i < rootNode.getChildCount(); i++) {
        if (rootNode.getChildCount() == 0) {
            continue;
        }
        AccessibilityNodeInfo accessibilityNodeInfo = rootNode.getChild(i);
        accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        if (WECHAT_RED_BUTTON.equals(accessibilityNodeInfo.getClassName())) {
            accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            break;
        } else {
            openRedPacket(accessibilityNodeInfo);
        }
    }
}

private void openRedPacket(AccessibilityNodeInfo rootNode) {
    for (int i = 0; i < rootNode.getChildCount(); i++) {
        if (rootNode.getChildCount() == 0) {
            continue;
        }
        AccessibilityNodeInfo accessibilityNodeInfo = rootNode.getChild(i);
        accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        if (WECHAT_RED_BUTTON.equals(accessibilityNodeInfo.getClassName())) {
            accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
    }
}

之前模拟过几种方法或多或少都有些其他问题,比如模拟按键屏幕位置(时间发现android 10.0小米手机未生效,模拟单点失败),cmd命令模拟adb shell put时间也失败了,然后现在拆字是个图片,没有找到资源ID的情况下也无法精准的点击,所以通过上述方法做了一个规避,从而实现了红包的点击;部分关键字的时候筛选过滤掉了相应的信息,实现了自动点击红包,拆开红包后需要对已经点击过的红包进行处理,监听TYPE_WINDOW_STATE_CHANGED事件:

private final static String WECHAT_RED_NAME = "微信红包";
private final static String WECHAT = "微信";
private final static String IS_GET_WECHAT_RED_NAME = "已领取";
private final static String IS_ALL_GET_WECHAT_RED_NAME = "已被领完";

        case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
            String className = event.getClassName().toString();
            AccessibilityNodeInfo rootNode = getRootInActiveWindow();
            if (WECHAT_UI.equals(className) || WECHAT_UI_2.equals(className)) {
                findRedPacket(rootNode);
            }
            if (WECHAT_RED.equals(className)) {
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        openRedPacket();
                        isOpenDetail = true;
                    }
                }, DELAY_TIME);

            }
            if (isOpenDetail && WECHAT_RED_DETAIL.equals(className)) {
                isOpenDetail = false;
                release();
            }
            break;
    }

这里可以进行锁屏、释放资源、终止服务等操作,由于事件问题,基础code里面并没有新增灭屏,唤醒,以及后台自动抢红包功能,后面会继续补充;

由于AccessibilityService服务很容易断开,所以我们需要将我们的App设置为白名单,另外需要重写MyAccessibilityService的终端监听等,上面基础code仅仅能支持微信聊天页面自动抢红包,拆红包,稳定性优化后续补充;

apk安装后记得在手机中打开无障碍服务

在这里插入图片描述
在这里插入图片描述
apk下载:

https://download.csdn.net/download/xiaweilihai/14927105

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值