Android实现QQ抢红包插件

又想到快要过年了,到时候还不知道群里要发好多红包,所以我将之前在网上宕的一份微信抢红包的代码修改了一下,实现了QQ抢红包!可以支持抢QQ拼手气红包,普通红包,口令红包,现在再也不怕20年单身手速的人跟我抢红包了!
先看测试效果图:
1.抢QQ口令红包 

可以看见,只要红包一发出,自动填写口令并发出,帮你将红包抢到手!
2.抢QQ拼手气红包

拼手气红包也是一样,只要红包一发出,自动帮你把红包抢到手,是不是很爽的感觉?
3.抢QQ好友发送的红包

只要好友或者群里的人把红包一发出,就会第一时间让你抢到红包!所以只要在群里面开启插件,抢红包从来都是百发百中!好了废话不多说了,也不吹嘘有多牛多好了,下面直接给大家上代码:

MainActivity:

/*MainActivity中的代码基本没改变:*/
public class MainActivity extends AppCompatActivity {
  private final Intent mAccessibleIntent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
  private Button switchPlugin;

  @Overrideprotected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    switchPlugin = (Button) findViewById(R.id.button_accessible);
    updateServiceStatus();
  }

  /*开启插件的按钮*/
  public void onButtonClicked(View view) {startActivity(mAccessibleIntent);}

  @Overrideprotected void onResume() {
    super.onResume();
    updateServiceStatus();
  }
}

  private void updateServiceStatus() {
    boolean serviceEnabled = false;
    AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
    List<AccessibilityServiceInfo> accessibilityServices = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
    for (AccessibilityServiceInfo info : accessibilityServices) {
      if (info.getId().equals(getPackageName() + "/.QQHongbaoService")) {
        serviceEnabled = true;
        break;
       }
     }
     if (serviceEnabled) {
       switchPlugin.setText("关闭插件");
       getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
     } else {
       switchPlugin.setText("开启插件");
       getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);}
   }
}

这里是MainActivity中的全部代码,是不是很少的样子,主要是实现了一个按钮去开启ACCESSIBILITY_SERVICE。这个插件主要就是借助AccessibilityService这个服务来实现。所以剩下的代码就都在这个服务中了!
QQHongbaoService:

public class QQHongbaoService extends AccessibilityService {
 private static final String WECHAT_OPEN_EN = "Open";
 private static final String WECHAT_OPENED_EN = "You've opened";
 private final static String QQ_DEFAULT_CLICK_OPEN = "点击拆开";
 private final static String QQ_HONG_BAO_PASSWORD = "口令红包";
 private final static String QQ_CLICK_TO_PASTE_PASSWORD = "点击输入口令";
 private boolean mLuckyMoneyReceived;
 private String lastFetchedHongbaoId = null;
 private long lastFetchedTime = 0;
 private static final int MAX_CACHE_TOLERANCE = 5000;
 private AccessibilityNodeInfo rootNodeInfo;
 private List<AccessibilityNodeInfo> mReceiveNode;

 @TargetApi(Build.VERSION_CODES.KITKAT)
 public void recycle(AccessibilityNodeInfo info) {
  if (info.getChildCount() == 0) {
   /*这个if代码的作用是:匹配“点击输入口令的节点,并点击这个节点”*/
   if(info.getText()!=null&&info.getText().toString().equals(QQ_CLICK_TO_PASTE_PASSWORD)) {
    info.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
    }
   /*这个if代码的作用是:匹配文本编辑框后面的发送按钮,并点击发送口令*/
   if (info.getClassName().toString().equals("android.widget.Button") && info.getText().toString().equals("发送")) {
    info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
    }
  } else {
    for (int i = 0; i < info.getChildCount(); i++) {
      if (info.getChild(i) != null) {
       recycle(info.getChild(i));
      }
     }
    }
  }

 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
 @Override
 public void onAccessibilityEvent(AccessibilityEvent event) {
  this.rootNodeInfo = event.getSource();
  if (rootNodeInfo == null) {
   return;
   }
  mReceiveNode = null;
  checkNodeInfo();
  /* 如果已经接收到红包并且还没有戳开 */
  if (mLuckyMoneyReceived && (mReceiveNode != null)) {
    int size = mReceiveNode.size();
    if (size > 0) {
      String id = getHongbaoText(mReceiveNode.get(size - 1));
      long now = System.currentTimeMillis();
      if (this.shouldReturn(id, now - lastFetchedTime))
       return;
      lastFetchedHongbaoId = id;
      lastFetchedTime = now;
      AccessibilityNodeInfo cellNode = mReceiveNode.get(size - 1);
      if (cellNode.getText().toString().equals("口令红包已拆开")) {
       return;
      }
      cellNode.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
      if (cellNode.getText().toString().equals(QQ_HONG_BAO_PASSWORD)) {
         AccessibilityNodeInfo rowNode = getRootInActiveWindow();
      if (rowNode == null) {
       Log.e(TAG, "noteInfo is null");
       return;
      } else {
         recycle(rowNode);
      }
     }
     mLuckyMoneyReceived = false;
     }
    }
  }

 private void checkNodeInfo() {
  if (rootNodeInfo == null) {
    return;
  }
  /* 聊天会话窗口,遍历节点匹配“点击拆开”,“口令红包”,“点击输入口令” */
  List<AccessibilityNodeInfo> nodes1 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{QQ_DEFAULT_CLICK_OPEN, QQ_HONG_BAO_PASSWORD, QQ_CLICK_TO_PASTE_PASSWORD, "发送"});
  if (!nodes1.isEmpty()) {
    String nodeId = Integer.toHexString(System.identityHashCode(this.rootNodeInfo));
    if (!nodeId.equals(lastFetchedHongbaoId)) {
    mLuckyMoneyReceived = true;
    mReceiveNode = nodes1;
     }    return;
   }
  }

 private String getHongbaoText(AccessibilityNodeInfo node) {
   /* 获取红包上的文本 */
   String content;
   try {
     AccessibilityNodeInfo i = node.getParent().getChild(0);
     content = i.getText().toString();
     } catch (NullPointerException npe) {
         return null;
       }
     return content;
  }

  private boolean shouldReturn(String id, long duration) {
    // ID为空
   if (id == null) return true;
   // 名称和缓存不一致
   if (duration < MAX_CACHE_TOLERANCE && id.equals(lastFetchedHongbaoId)) {
     return true;
    }
   return false;
  }

  private List<AccessibilityNodeInfo> findAccessibilityNodeInfosByTexts(AccessibilityNodeInfo nodeInfo, String[] texts) {
    for (String text : texts) {
      if (text == null) continue;
      List<AccessibilityNodeInfo> nodes = nodeInfo.findAccessibilityNodeInfosByText(text);
      if (!nodes.isEmpty()) {
        if (text.equals(WECHAT_OPEN_EN) && !nodeInfo.findAccessibilityNodeInfosByText(WECHAT_OPENED_EN).isEmpty()) {
          continue;
        }
        return nodes;
      }
     }
    return new ArrayList<>();
  }

  @Override
  public void onInterrupt() {}
}

QQHongbaoService的全部代码也在这里,代码不多。首先,在这个服务中主要是通过findAccessibilityNodeInfosByText这个方法去获我们需要的节点;然后用performAction(AccessibilityNodeInfo.ACTION_CLICK)这个方法去点击红包节点,关键思路大概就是这样!另外如果是口令红包,我们需要先按照上面的步骤将红包戳开,然后通过performAction(AccessibilityNodeInfo.ACTION_CLICK)去点击输入口令,最后再通过点击去发送即可实现!QQHongbaoService需要在AndroidManifest.xml文件中注册,
注册的<application>节点如下图:

总体来看,只是将微信抢红包的代码做了少量的修改,在这里要感谢各位大神对微信抢红包源码的贡献!最后也希望这篇文章能给大家有所帮助,在抢红包大战中虐死单身狗,再也不怕你20年的单身手速了!!!

(0)

相关推荐

  • Android系统实现DroidPlugin插件机制

    360手机助手使用的 DroidPlugin,它是360手机助手团队在Android系统上实现了一种插件机制.它可以在无需安装.修改的情况下运行APK文件,此机制对改进大型APP的架构,实现多团队协作开发具有一定的好处. 它是一种新的插件机制,一种免安装的运行机制 github地址:https://github.com/DroidPluginTeam/DroidPlugin 参考博客:http://blog.csdn.net/hejjunlin/article/details/52124397

  • 分享Android微信红包插件

    本文实例为大家分享了Android微信红包插件,供大家参考,具体内容如下 效果图: 具体代码 @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void handleWindowChange(AccessibilityNodeInfo nodeInfo) { switch (Stage.getInstance().getCurrentStage()) { case Stage.OPENING_STAGE: // 调试信息,打印TTL // Lo

  • Android桌面插件App Widget用法分析

    本文实例讲述了Android桌面插件App Widget用法.分享给大家供大家参考,具体如下: 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget)是微小的应用程序视图,可以被嵌入到其它应用程序中(比如桌面)并接收周期性的更新.你可以通过一个App Widget provider来发布一个Widget.可以容纳其它App Widget的应用程序组件被称为App Widget宿主.下面的截屏显示了一个音乐App Widget. appwidget 这篇文章描述了如何使用Ap

  • 解析离线安装Eclipse的Android ADT开发插件的具体操作(图文)

    不知道大家是不是有过这样的感觉.从 https://dl-ssl.google.com/android/eclipse/很慢呢!我是教育网所以确实是很慢的.所以我想了一个办法确保可以快点安装上ADT15.当然ADT16.ADT17也是可以的.不过我还是用ADT15做演示把.(注意:不同的SDK对应的ADT版本也不同,同时在安装时要断开网络) 很熟悉把,这是Eclipse解压后的图片当然ADT是要自己下载的.我们51CTO下载哪儿也有好多的,大家自己去下载,我就不提供下载地址啦. 打开Eclips

  • Android中微信抢红包插件原理解析及开发思路

    一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导致了.或许是网络的原因,而且这个也是最大的原因.但是其他的不可忽略的因素也是要考虑到进去的,比如在手机充电锁屏的时候,我们并不知道有人已经开始发红包了,那么这时候也是让我们丧失了一大批红包的原因.那么关于网络的问题,我们开发者可能用相关技术无法解决(当然在Google和Facebook看来的话,他们

  • APP添加CNZZ统计插件教程 Android版添加phonegap

    KeyMob移动广告平台是精准稳定的广告SDK.移动广告平台,致力于塑造国内最具有影响力的移动广告平台.主营移动广告服务,横跨IOS.Android两大平台,包含横幅.插屏.全屏.视频广告.banner等多种广告形式. 一.导入JAR包 使用Eclipse进行开发的用户,首先将下载的MobileProbe.jar解压到本地工程目录下的libs子目录里面(例如,您的工程目录为,D:workspaceXXproject,请将MobileProbe.jar放入D:workspaceXXprojectl

  • 为Android Studio编写自定义Gradle插件的教程

    Google已经建议Android开发全部转向Android Studio开发,Android Studio 是使用gradle编译.打包的,那么问题来了,gradle可是有一堆东西...,为了彻底了解gradle,今天就来学习下如何写自己的gradle插件(当然插件源码是使用groovy写的),先看如下代码目录: 如上图所示,plugin目录是插件源码目录,sample是用来测试插件的. 1.在目录plugin/src/main/groovy/com/micky/gradle/下新建插件类My

  • Android抢红包插件实现原理浅析

    抢红包,先看效果图~ 实现自动抢红包,解决问题有两点: 一:如何实时监听发红包的事件 二:如何在红包到来的时候自动进入页面并自动点击红包 一.如何获取红包到来的事件 为了获取红包到来状态栏的变化,我们要用到一个类:Accessibility 许多Android使用者因为各种情况导致他们要以不同的方式与手机交互. 这包括了有些用户由于视力上,身体上,年龄上的问题致使他们不能看完整的屏幕或者使用触屏,也包括了无法很好接收到语音信息和提示的听力能力比较弱的用户. Android提供了Accessibi

  • Android微信自动抢红包插件优化和实现

    又是兴趣系列 网上有很多自动强红包的例子和代码,笔者也是做了一些优化. 先说说自己的两个个优势 1.可以在聊天界面自动强不依赖于通知栏推送 2.可以在屏幕熄灭的时候的时候点亮屏幕自动抢(目前只测过flyme) 先上图: 代码传送门: https://github.com/AndroidMsky/WXhongbao 欢迎点星星~ 原理: 通过AccessibilityService监听到状态栏通知,进行模拟点击,获取屏幕中view节点为领取红包的list并且点击最后一个. 如果不通过状态栏通知,通

  • Android上使用jspf插件框架的方法

    本文实例讲述了Android上使用jspf插件框架的方法.分享给大家供大家参考.具体如下: jspf (Java Simple Plugin Framework) 是一个插件框架,集成了很多 IoC 框架的概念在里面. package de.jspfdemo; import net.xeoh.plugins.base.PluginManager; import net.xeoh.plugins.base.impl.PluginManagerFactory; import net.xeoh.plu

随机推荐