zoukankan      html  css  js  c++  java
  • 微信自动抢红包android实现

    AccessibilityService-微信自动抢红包

    在领导发红包的时候,看到有些同事在1s、2s抢到红包,为什么他们能够这么快?一定是“开挂”的想法立马浮现出来。

    做一个程序猿,为什么不自己写一个呢?

    借助Android的辅助功能的AccessibilityService服务就能够做到。

    1.  检测当前界面是否有红包(未拆开的红包)
    2. 让手机自动点击发现的红包(未拆开的红包)
    3. 检测拆红包弹出窗口上那个“开”的按钮,并让手机自动点击
    4. 进入红包详情界面,检测到返回按钮,自动点击返回到聊天界面,继续抢红包
    一、创建Android Project后,先来编辑AccessibilityService的配置accessible_service_config.xml
    1.  
      <?xml version="1.0" encoding="utf-8"?>
    2.  
      <accessibility-service
    3.  
      xmlns:android="http://schemas.android.com/apk/res/android"
    4.  
      android:description="@string/app_name"
    5.  
      android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
    6.  
      android:accessibilityFeedbackType="feedbackGeneric"
    7.  
      android:accessibilityFlags="flagDefault"
    8.  
      android:canRetrieveWindowContent="true"
    9.  
      android:notificationTimeout="10"
    10.  
      android:packageNames="com.tencent.mm"
    11.  
      />
    android:accessibilityEventTypes 辅助服务关注的事件类型
    当前配置:typeWindowStateChanged|typeWindowContentChanged(对应等下需要使用到的事件)
    android:accessibilityFeedbackType 事件的反馈给用户的方式
    当前配置:feedbackGeneric(通用)
    android:accessibilityFlags 辅助服务额外的flag信息
    当前配置:flagDefault(默认)
    android:canRetrieveWindowContent 是否可以获取窗口内容
    当前配置:true
    android:notificationTimeout 两个同样类型的辅助事件发给辅助服务的最小时间间隔
    当前配置:10
    android:packageNames 辅助服务监听的应用包名,可监听多个应用包名,使用逗号隔开。
    当前配置:com.tencent.mm(监听微信发出的事件)
    二、在AndroidManifest.xml中注册AccessibilityService服务
    <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
    1.  
      <service
    2.  
      android:name=".LooterService"
    3.  
      android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    4.  
      <intent-filter>
    5.  
      <action android:name="android.accessibilityservice.AccessibilityService" />
    6.  
      </intent-filter>
    7.  
      <meta-data
    8.  
      android:name="android.accessibilityservice"
    9.  
      android:resource="@xml/accessible_service_config" />
    10.  
      </service>
    1. AccessibilityService需要权限android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
    2. 添加intent-filter下的action android:name="android.accessibilityservice.AccessibilityService"
    三、创建继承AccessibilityService的服务类LooterService(检测的id基于微信6.6.1版本)
    在accessible_service_config.xml配置了android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged",所以这里监听
    窗口界面的内容是否改变当发生变化时(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED),就有进入到下面的if中:
    //如果当前的事件类型是窗口内容出现了变化,那么判断是否有红包视图出现
    
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED){
            List<AccessibilityNodeInfo> hongbaoList = mRootNodeInfo.findAccessibilityNodeInfosByText("微信红包");
            List<AccessibilityNodeInfo> weikaiList = mRootNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/aeb");
            Log.e("looter","发现红包检测数量 : " + hongbaoList.size());
            for (int i = 0; i < weikaiList.size(); i++) {
                if (weikaiList.get(i).getText().equals("领取红包")){
                    AccessibilityNodeInfo curNodeInfo = weikaiList.get(i);
                    curNodeInfo.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
                }
            }
        }
    通过findAccessibilityNodeInfosByText("微信红包")获取红包数量list;
    通过findAccessibilityNodeInfosByViewId("com.tencent.mm:id/aeb"),根据特定id获取到红包item节点list。(下面再说下怎么获取到对应微信版本的id)
    在for循环里,通过条件 if (weikaiList.get(i).getText().equals("领取红包"))匹配未拆开的红包item节点,
    getParent()拿到父节点,父节点.performAction(AccessibilityNodeInfo.ACTION_CLICK)进行模拟点击。
    模拟点击后,弹出红包窗口,这时候监听到窗口的状态发生变化(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)进入下面的if中:
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){
        List<AccessibilityNodeInfo> clickedWindowList = mRootNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/c2i");
        if (clickedWindowList.size() > 0){
            AccessibilityNodeInfo curNodeInfo1 = clickedWindowList.get(0);
            curNodeInfo1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
    }
    通过findAccessibilityNodeInfosByViewId("com.tencent.mm:id/c2i"),根据特定id获取到“開”控件的节点list。
    这里就不用去getParent()拿父节点了,直接进行模拟点击,把红包拆开。
    进入到红包详情界面,窗口状态发生变化,上下的if中的代码都会执行到,由于红包详情界面没有com.tencent.mm:id/c2i这个id,所以没有进行模拟点击(拆红包)。
    检测到com.tencent.mm:id/ho这个的item节点,模拟点击,返回到聊天界面,继续检测是否未拆开的红包。
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){
        List<AccessibilityNodeInfo> backlist = mRootNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/ho");
        if (backlist.size() > 0){
            AccessibilityNodeInfo curNodeInfo1 = backlist.get(0);
            curNodeInfo1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
    }
    再说下怎么获取到对应微信版本的控件id
    使用Android Studio内部的工具Android Device Monitor
    点击Dump View Hierarchy for UI Automator这个按钮
    这个dump界面截图上点击领取红包,在右侧resource-id一栏中出现这个控件的id。
    后续的控件id,依样画葫芦就能获取到对应控件id。
    在最后贴一下LooterService这个类的完整代码:
    public class LooterService extends AccessibilityService {
        //该对象代表了整个窗口视图的快照
        private AccessibilityNodeInfo mRootNodeInfo = null;
        @Override
        public void onAccessibilityEvent(AccessibilityEvent event) {
            mRootNodeInfo = event.getSource();
            if (mRootNodeInfo == null){
                return;
            }
            //如果当前的事件类型是窗口内容出现了变化,那么判断是否有红包视图出现
            try {
                if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED){
                    List<AccessibilityNodeInfo> hongbaoList = mRootNodeInfo.findAccessibilityNodeInfosByText("微信红包");
                    List<AccessibilityNodeInfo> weikaiList = mRootNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/aeb");
                    Log.e("looter","发现红包检测数量 : " + hongbaoList.size());
                    for (int i = 0; i < weikaiList.size(); i++) {
                        Log.e("looter","  ---  weikaiList.get(i).getText()  --- " + weikaiList.get(i).getText() );
                        if (weikaiList.get(i).getText().equals("领取红包")){
                            AccessibilityNodeInfo curNodeInfo = weikaiList.get(i);
                            curNodeInfo.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
                        }
                    }
                }
                if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){
                    List<AccessibilityNodeInfo> clickedWindowList = mRootNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/c2i");
                    if (clickedWindowList.size() > 0){
                        AccessibilityNodeInfo curNodeInfo1 = clickedWindowList.get(0);
                        curNodeInfo1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                }
                if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){
                    List<AccessibilityNodeInfo> backlist = mRootNodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/ho");
                    if (backlist.size() > 0){
                        AccessibilityNodeInfo curNodeInfo1 = backlist.get(0);
                        curNodeInfo1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        @Override
        public void onInterrupt() {
    
        }
    }
    这是这个项目的导出apk包,之前上传的资源。下载分数感觉高,后面重新上传了一个,被拒了。
    http://download.csdn.net/download/u014506842/10194630
  • 相关阅读:
    js,jquery小知识点
    httpd.conf中文祥解(转载)
    web_report_data_point(原创)
    用lr查看apache的服务情况
    检查链接的工具
    DNS缓存(转载)
    在linux下使用用Valgrind查找内存泄漏和无效内存访问(转载)
    初次接触php
    qtp 基础代码转载自51testing中的kai_top 网友。
    descriptive programming转载51testing 作者:周坚
  • 原文地址:https://www.cnblogs.com/timssd/p/9486053.html
Copyright © 2011-2022 走看看