基于AccessiblityService实现抢红包APP

功能:兼容多种情况下抢到微信红包:锁屏状态下、不在微信界面下、在微信主界面下、群屏蔽下、聊天界面出现连续的红包雨等情况;抢红包速度:2-3秒/个(小米、魅族手机只能跳到红包界面,无法实现自动领取,其他手机型号均可)

设计思路:调用Android系统自带的AccessibilityService服务监控手机消息状态(为了防止受其他非微信类消息的干扰,设置只监控“com.tencent.mm”的包名;为了保证可以兼容多种情况下可以抢到到红包,如锁屏状态下、不在微信界面下、在微信主界面下、群屏蔽下、聊天界面出现连续的红包雨等情况,需设置监控状态有TYPE_NOTIFICATION_STATE_CHANGED (通知栏变化)、TYPE_WINDOW_CONTENT_CHANGED(界面内容变化)、TYPE_WINDOW_STATE_CHANGED(窗口体变化)然后根据状态变化出现“[微信红包]”的文字,则调用AccessibilityService的ACTION_CLICK模拟点击进入红包界面并领取,完成自动抢红包的操作;最后执行GLOBAL_ACTION_BACK返回聊天界面。

程序流程图:


代码解析:

(1)在MainActivity跳转到手机无障碍模式界面,提示用户打开AccessibilityService服务

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            //打开系统设置中辅助功能
            Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
            startActivity(intent);
            Toast.makeText(this, "group04_抢红包APP->开启", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

(2)重写AccessibilityService的继承类,并在里面重写onAccessibilityEvent函数,实时监控微信的动态。红包消息变化状态依次分为三类:

  •  以消息栏形式弹出(该情况一般出现于手机锁屏、正在使用其他APP、处于与非发红包者聊天界面)当红包消息以Notification的形式出现,先判断是否处于锁屏状态,调用wakeAndUnlock()函数(自己写的函数)解锁;然后用PendingIntent跳转到微信聊天界面,这时手机的state变化了,跳转到窗口体变化状态
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:// 通知栏事件
                Log.d("eventType","notification event");
                List<CharSequence> texts = event.getText();
                if (!texts.isEmpty()) {
                    for (CharSequence text : texts) {
                        String content = text.toString();
                        Log.v("content",content);
                        if(content.contains("[微信红包]")){
                            //如果锁定,先解锁
                            if(isScreenLocked()){
                                wakeAndUnlock();
                                Log.d("i","解锁");
                            }
                            hasNotification =  true;
                            //打开微信界面
                            Notification notification =(Notification)event.getParcelableData();
                            if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
                                PendingIntent pendingIntent = notification.contentIntent;
                                try {
                                    pendingIntent.send();
                                    Log.d("i","打开微信界面");
                                } catch (PendingIntent.CanceledException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
                break;
  •  窗口体变化(只有打开微信界面时,才会出现窗口界面的变化
  • case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED://窗口体状态,事件源:跳转到新的页面,或者弹出了window,dialog等
                    Log.d("eventType","Window event");
                    String className = event.getClassName().toString();
                    Log.d("窗口体变化",className);
                    if(hasNotification){//先判断hasNotification为true,说明是进入有红包的聊天界面,以免所有的通知信息都进入聊天界面
                        if(className.equals("com.tencent.mm.ui.LauncherUI")){
                            Log.d("e","进入微信界面");
                            openPacket();
                        }
                        else if(className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI") ){
                            Log.d("i","进入点击红包界面");
                            receivePacket();
                        }
                        else if(className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")){
                            Log.d("e","进入红包记录界面");
                            release();
                            //可以在这里用handler进行抢红包延时
                            performGlobalAction(GLOBAL_ACTION_BACK);
                        }
                    }
                    break;


  • 窗口内容变化(这种情况用来检测聊天界面变化如连续发红包、微信主界面出现微信红包的消息(此时不会以通知栏的形式出现,而是发生窗口view变化))
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED://某个view的内容发生的变化,对于红包而言:出现在打开微信却不是在com.tencent.mm.ui.LauncherUI界面或者出现红包雨的情况下或者只要微信有消息就行
                Log.d("eventType","View event");
                String className_view = event.getClassName().toString();
                Log.d("view变化",className_view);
                hasPacketInWXforground();//过滤掉微信主界面不是微信红包的信息,只进入有微信红包的聊天界面
                openPacket();
                hasNotification = true;
                break;

(3)打开红包界面:获取该界面的包含“领取红包”Text的所有节点,然后getParent()得到父节点,点击父节点即可进入领取红包界面。

private void openPacket(){
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if(nodeInfo == null) return ;
        //获取该界面的包含“领取红包”Text的所有节点
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("领取红包");
        if(list.size()==0) return;
        Log.d("i",list.size()+"个红包可以领取");
        //最新的红包领起
        for (int i = list.size() - 1; i >= 0; i--) {
            AccessibilityNodeInfo parent = list.get(i).getParent();//获取该节点的父节点
            if (parent != null) {
                parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);//模拟点击
                break;
            }
        }
    }

(4)领取红包:利用Android studio里面Uiautomator获取微信“开”图片的id为com.tencent.mm:id/c31,所以只要找出所有含该id的节点,模拟点击即可领取。


PS:这里的id在最新的微信版本/2018.6.2可能会不同,如果不是以上的id,可以通过AS的UIutomator获取新的id

最新微信6.6.7版本id为:com.tencent.mm:id/c85

private void receivePacket() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            Log.d("node","数量为null");
            return;
        }
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/c85");//打开红包按钮的id
        Log.d("i", list.size() + "个红包可以领取");
        for (AccessibilityNodeInfo n : list) {
            if (n.isClickable()) {
                n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                Log.d("i", "领取成功");
                break;
            }
        }
        //说明已经没有红包领了,让通知栏判断为false
        if (list.size()==0) {
            hasNotification = false;
            Log.d("d", "没有通知了");
        }
    }

(5)当处于微信主界面时,判断有新的红包消息,并进入领取

//当我们在微信主界面时,有新消息接收,不会以通知栏的形式出现,需要自行判断是否有红包(判断id:com.tencent.mm:id/apx)
    private void hasPacketInWXforground(){
        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        if(rootNode==null) return ;
        List<AccessibilityNodeInfo> list = rootNode.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/apx");//该id判断栏目的第二小行的第二列,如新消息里的XX:[微信红包]大吉大利,其中[微信红包]..就是
        for(int i=0;i<list.size();i++){
            String content = list.get(i).getText().toString();
            if(content.contains("[微信红包]")){
                AccessibilityNodeInfo parent = list.get(i).getParent();
                List<AccessibilityNodeInfo> list_new = parent.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/jj");//新消息的数量,含数字的小红球
                List<AccessibilityNodeInfo> list_mute = parent.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/apu");//已经屏蔽的群信息
                //过滤掉已阅览的群节点
                if((list_new.size()>0 || list_mute.size()>0) && parent.isClickable()){
                    Log.d("i","进入聊天界面");
                    parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    break;
                }
            }
        }
    }

(6)红包记录界面:该界面在窗口体state判断,需要返回上一级,调用返回键GLOBAL_ACTION_BACK退出红包记录界面,继续执行抢红包操作 

else if(className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")){
                        Log.d("e","进入红包记录界面");
                        release();
                        //可以在这里用handler进行抢红包延时
                        performGlobalAction(GLOBAL_ACTION_BACK);
                    }

测试结果:

微信昵称为:益智 的手机号安装编写好的抢红包APP,其他三个人同时发红包到实验群,并以最快的速度开抢,所得结果如下:


由图可知:安装APP的微信号保持每两秒抢到一个红包的速度,时间分别为1:12:50->1:12:52->1:12:54;而没有APP的微信号每抢到一个红包至少需要3秒,如微信昵称为:做实验的小号,抢到红包时间分别为:1:12:50->1:12:54->1:12:57,每次间隔为3秒

代码下载:

Github下载

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值