教你一步步实现Android微信自动抢红包

本文介绍微信自动抢红包的实现方法,主要实现以下几个功能:

1.自动拆开屏幕上出现的红包

2.处于桌面或聊天列表时接收到红包信息时自动进入聊天界面并拆红包

3.日志功能,记录抢红包的详细日志

实现原理

1.利用AccessibilityService辅助服务,监测屏幕内容,实现自动拆红包的目的。

2.利用ActiveAndroid数据库简单记录红包日志

3.利用preference实现监控选项纪录

最终界面

抢红包核心代码

AccessibilityService配置

android:accessibilityEventTypes 设置触发监听回调的事件类型;

android:packageNames 设置监听的应用,这里监听的是微信,因此填上微信的包名com.tencent.mm

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged"
 android:accessibilityFeedbackType="feedbackGeneric"
 android:accessibilityFlags="flagDefault"
 android:canRetrieveWindowContent="true"
 android:description="@string/accessibility_description"
 android:notificationTimeout="100"
 android:packageNames="com.tencent.mm"
 android:settingsActivity="com.oden.annotations.app.activity.ManActivity" />

在AndroidManifest.xml中声明:

 <service
   android:name=".app.service.HongbaoService_"
   android:enabled="true"
   android:exported="true"
   android:label="@string/app_name"
   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>

抢红包实现代码

接收系统发送来的AccessibilityEvent

 private static final String GET_RED_PACKET = "领取红包";
 private static final String CHECK_RED_PACKET = "查看红包";
 private static final String RED_PACKET_PICKED = "手慢了,红包派完了";
 private static final String RED_PACKET_PICKED2 = "手气";
 private static final String RED_PACKET_PICKED_DETAIL = "红包详情";
 private static final String RED_PACKET_SAVE = "已存入零钱";
 private static final String RED_PACKET_NOTIFICATION = "[微信红包]";

 @Override
 public void onAccessibilityEvent(AccessibilityEvent event) {
  L.d("RECEIVE EVENT!");
  if (watchedFlags == null) return;
   /* 检测通知消息 */
  if (!mMutex) {
   if (watchedFlags.get("pref_watch_notification") && watchNotifications(event)) return;
   if (watchedFlags.get("pref_watch_list") && watchList(event)) return;
  }
  if (!watchedFlags.get("pref_watch_chat")) return;

  this.rootNodeInfo = event.getSource();
  if (rootNodeInfo == null) return;

  mReceiveNode = null;
  mUnpackNode = null;

  checkNodeInfo();

   /* 如果已经接收到红包并且还没有戳开 */
  if (mLuckyMoneyReceived && !mLuckyMoneyPicked && (mReceiveNode != null)) {
   mMutex = true;
   AccessibilityNodeInfo cellNode = mReceiveNode;
   cellNode.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
   mLuckyMoneyReceived = false;
   mLuckyMoneyPicked = true;
   L.d("正在打开!");
  }

   /* 如果戳开但还未领取 */
  if (mNeedUnpack && (mUnpackNode != null)) {
   AccessibilityNodeInfo cellNode = mUnpackNode;
   cellNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
   mNeedUnpack = false;
   L.d("正在领取!");
  }

  if (mNeedBack) {
   performGlobalAction(GLOBAL_ACTION_BACK);
   mMutex = false;
   mNeedBack = false;
   L.d("正在返回!");
   //总次数和金额统计
   if (isGetMoney) {
    T.showShort(this, "抢到一个红包: " + gotMoney + "元!");
    totalMoney = totalMoney + gotMoney;
    totalSuccessNum++;
    myPrefs.totalMoney().put(totalMoney);
    myPrefs.successNum().put(totalSuccessNum);
    L.d("totalMoney: " + totalMoney);
    L.d("totalSuccessNum: " + totalSuccessNum);
    saveToLog(hongbaoInfo);
    isGetMoney = false;
   }
  }
 }

检测监听事件的节点信息

private void checkNodeInfo() {
  L.d("checkNodeInfo!");
  if (this.rootNodeInfo == null) return;
   /* 聊天会话窗口,遍历节点匹配“领取红包”和"查看红包" */
  List<AccessibilityNodeInfo> nodes1 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
    GET_RED_PACKET, CHECK_RED_PACKET});
  if (!nodes1.isEmpty()) {
  L.d("!nodes1.isEmpty()");
   AccessibilityNodeInfo targetNode = nodes1.get(nodes1.size() - 1);
   if ("android.widget.LinearLayout".equals(targetNode.getParent().getClassName()))//避免被文字干扰导致外挂失效
   {
    if (this.signature.generateSignature(targetNode)) {
     mLuckyMoneyReceived = true;
     mReceiveNode = targetNode;
     L.d("signature:" + this.signature.toString());
    }
   } else {
    L.d("this is text");
   }
   return;
  }

  List<AccessibilityNodeInfo> nodes2 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
    "拆红包"});
  if (!nodes2.isEmpty()) {
   L.d("node2 != null");
   for (AccessibilityNodeInfo nodeInfo : nodes2) {
     if (nodeInfo.getClassName().equals("android.widget.Button"))
      nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
   }
  } else {
    /* 戳开红包,红包还没抢完,遍历节点匹配“拆红包” */
   AccessibilityNodeInfo node2 = (this.rootNodeInfo.getChildCount() > 3) ? this.rootNodeInfo.getChild(3) : null;
   if (node2 != null && node2.getClassName().equals("android.widget.Button")) {
    mUnpackNode = node2;
    mNeedUnpack = true;
    isToGetMoney = true;
    L.d("find red packet!");
    return;
   }
  }
   /* 戳开红包,红包已被抢完,遍历节点匹配“已存入零钱”和“手慢了” */
  if (mLuckyMoneyPicked) {
   List<AccessibilityNodeInfo> nodes3 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
     RED_PACKET_PICKED, RED_PACKET_SAVE, RED_PACKET_PICKED2, RED_PACKET_PICKED_DETAIL});
   if (!nodes3.isEmpty()) {
    L.d("!nodes3.isEmpty()");
    if (rootNodeInfo.getChildCount() > 1) {
     L.d("RED_PACKET_PICKED!");
    } else {
     L.d("nodes3.get(0).toString(): " + nodes3.get(0).getText().toString());
     if (!nodes3.get(0).getText().toString().equals(RED_PACKET_PICKED_DETAIL)) {
      AccessibilityNodeInfo targetNode = nodes3.get(nodes3.size() - 1);
      hongbaoInfo.getInfo(targetNode);
      if (isToGetMoney) {
       isGetMoney = true;
       isToGetMoney = false;
       gotMoney = hongbaoInfo.getMoney();
       L.d("gotMoney: " + gotMoney);
      }
      L.d("RED_PACKET_SAVE!");
      L.d("hongbaoInfo: " + hongbaoInfo.toString());
     } else {
      L.d("this packet is myself!");
     }

    }
    mNeedBack = true;
    mLuckyMoneyPicked = false;
   }
  }
 }

主要通过检测“领取红包”等关键文字信息来判断是否有新红包

检测收到红包时判断是否"android.widget.LinearLayout",屏蔽聊天信息中的文字干扰

拆红包时,由于微信版本可能不同,同时进行两种判断,以兼容部分版本

拆完红包需自动返回,有以下几种情况:抢到了,手慢了,以及该红包是自己发出的红包

下面是监听聊天列表的代码:

private boolean watchList(AccessibilityEvent event) {
  // Not a message
  if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || event.getSource() == null)
   return false;

  List<AccessibilityNodeInfo> nodes = event.getSource().findAccessibilityNodeInfosByText(RED_PACKET_NOTIFICATION);
  if (!nodes.isEmpty()) {
   AccessibilityNodeInfo nodeToClick = nodes.get(0);
   CharSequence contentDescription = nodeToClick.getContentDescription();
   if (contentDescription != null && !lastContentDescription.equals(contentDescription)) {
    nodeToClick.performAction(AccessibilityNodeInfo.ACTION_CLICK);
    lastContentDescription = contentDescription.toString();
    return true;
   }
  }
  return false;
 }

下面是监听通知信息的代码:

 private boolean watchNotifications(AccessibilityEvent event) {
  // Not a notification
  if (event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)
   return false;

  // Not a hongbao
  String tip = event.getText().toString();
  if (!tip.contains(RED_PACKET_NOTIFICATION)) return true;

  Parcelable parcelable = event.getParcelableData();
  if (parcelable instanceof Notification) {
   Notification notification = (Notification) parcelable;
   try {
    notification.contentIntent.send();
   } catch (PendingIntent.CanceledException e) {
    e.printStackTrace();
   }
  }
  return true;
 }

红包信息的获取,及日志的存储

通过获取节点的子信息,分别获得红包发送者及抢到的金额、抢红包时间等信息,建立简单的表单分别记录该信息。

@Table(name = "HongbaoInfos")
public class HongbaoInfo extends Model {

 private int month;
 private int day;
 private int hour;
 private int min;
 private int sec;

 @Column(name = "sender")
 public String sender;

 @Column(name = "money")
 public String money;

 @Column(name = "time")
 public String time;

 public void getInfo(AccessibilityNodeInfo node) {

  AccessibilityNodeInfo hongbaoNode = node.getParent();
  sender = hongbaoNode.getChild(0).getText().toString();
  money = hongbaoNode.getChild(2).getText().toString();
  time = getStringTime();
 }

 private String getStringTime() {
  Calendar c = Calendar.getInstance();
  month = c.get(Calendar.MONTH) + 1;
  day = c.get(Calendar.DAY_OF_MONTH);
  hour = c.get(Calendar.HOUR_OF_DAY);
  min = c.get(Calendar.MINUTE);
  sec = c.get(Calendar.SECOND);
  return month+"月"+day+"日 "+hour+":"+min+":"+sec;
 }

 @Override
 public String toString() {
  return "HongbaoInfo [sender=" + sender + ", money=" + money + ", time=" + time + "]";
 }

 public static List<HongbaoInfo> getAll() {
  return new Select()
    .from(HongbaoInfo.class)
    .orderBy("Id ASC")
    .execute();
 }

 public static void deleteALL() {
  new Delete().from(HongbaoInfo.class).execute();
 }

 public float getMoney() {
  return Float.parseFloat(money);
 }

 public String getSender() {
  return sender;
 }

 public String getTime() {
  return time;
 }
}

存储操作:

 private void saveToLog(HongbaoInfo hongbaoInfo) {
  if (watchedFlags.get("pref_etc_log")) {
   HongbaoInfo hongbaoInfo1 = new HongbaoInfo();
   hongbaoInfo1 = hongbaoInfo;
   hongbaoInfo1.save();
  } else {
   L.d("log closed!");
  }
 }

总结

主要的代码到这里基本结束,目前在微信最新版上测试ok,尚还存在以下几个问题:

1.同一个人连续发的不能自动抢,因为为了防止重复点击做了过滤,同一个人的红包抢了后不会再次点击

2.AccessibilityService开启时间长后有时会被系统关掉

结束语

以上就是本文的全部内容了,希望对大家的学习和工作能有所帮助。

(0)

相关推荐

  • Android辅助功能实现自动抢红包(附源码)

    一.描述 最近看到同事有用抢红包的软件,就想看看抢红包的具体实现是如何的,所以了解了一下,有用辅助功能实现的,所以在下面的示例中会展示一个抢红包的小Demo,附带源码抢红包源码. 二.效果图 在桌面收到红包进行抢 在聊天页面收到口令红包 三.AccessibilityService使用 创建辅助服务类,继承AccessibilityService,实现两个接口,接收系统的事件 public class MyService extends AccessibilityService { @Overr

  • Android实现微信自动抢红包的程序

    简单实现了微信自动抢红包的服务,原理就是根据关键字找到相应的View, 然后自动点击.主要是用到AccessibilityService这个辅助服务,基本可以满足自动抢红包的功能,但是有些逻辑需要优化,比如,拆完一个红包后,必须手动点击返回键,才能进行下一次自动抢红包. AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="h

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

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

  • 教你一步步实现Android微信自动抢红包

    本文介绍微信自动抢红包的实现方法,主要实现以下几个功能: 1.自动拆开屏幕上出现的红包 2.处于桌面或聊天列表时接收到红包信息时自动进入聊天界面并拆红包 3.日志功能,记录抢红包的详细日志 实现原理 1.利用AccessibilityService辅助服务,监测屏幕内容,实现自动拆红包的目的. 2.利用ActiveAndroid数据库简单记录红包日志 3.利用preference实现监控选项纪录 最终界面 抢红包核心代码 AccessibilityService配置 android:access

  • IOS 实现微信自动抢红包(非越狱IPhone)

    iOS微信自动抢红包(非越狱) 现在微信红包很流行,尤其在微信群里发红包,如果没有及时抢红包,根本抢不到,于是就想是不是能写个插件之类的实现自动抢红包呢,经过在网上查询资料,实现了该功能,如下: 微信红包 前言:最近笔者在研究iOS逆向工程,顺便拿微信来练手,在非越狱手机上实现了微信自动抢红包的功能. 题外话:此教程是一篇严肃的学术探讨类文章,仅仅用于学习研究,也请读者不要用于商业或其他非法途径上,笔者一概不负责哟~~ 好了,接下来可以进入正题了! 此教程所需要的工具/文件 yololib cl

  • 使用AccessibilityService实现微信自动切换账号功能

    对AccessibilityService的学习已经有一个多月了,发现其使用方法其实也都蛮简单的,只是在不同项目中试错比较复杂. 使用AccessibilityService实现了微信自动切换账号的功能,图示如下(这个步骤都是全自动的喔): 使用方式是运行程序-开启无障碍服务,再切换到微信主界面,点击[我]的tab按钮,就会自动执行退出账号再登陆的逻辑了. AccessibilityService使用基础: Android辅助服务类主要是方便一些试听有障碍的用户实现无障碍服务的工具,直白的说就是

  • android 微信抢红包工具AccessibilityService实现详解

    目录 1.目标 2.实现流程 1.流程分析(这里只分析在桌面的情况) 2.实现步骤 1.收到通知 以及 点击通知栏 2.点击红包 3.点击开红包 4.退出红包详情页 3.遇到问题 4.完整代码 MyNotificationListenerService MyAccessibilityService 5.总结 你有因为手速不够快抢不到红包而沮丧? 你有因为错过红包而懊恼吗? 没错,它来了... 1.目标 使用AccessibilityService的方式,实现微信自动抢红包(吐槽一下,网上找了许多

  • Android实现微信自动向附近的人打招呼(AccessibilityService)

    学习功能强大的AccessibilityService!!! 以下是本人根据自动抢红包的实现思路敲的用于微信自动向附近的人打招呼的核心代码 public class AutoService extends AccessibilityService implements View.OnClickListener { private static final String TAG = "test"; /** * 微信的包名 */ static final String WECHAT_PAC

  • Android 微信摇骰子和猜拳作弊器原理解析

    一.前言 在之前的一篇文章中我们已经详细介绍了Android中Hook工作的一款神器Xposed工具:Xposed框架原理解析和使用案例分析 在那一篇文章中我们介绍了如何安装Xposed框架,以及如何使用Xposed库编写第一个模块来做到修改系统方法功能的效果,同时也说到了一个非常重要的知识点就是:在Hook过程中最重要的一点就是如何找到Hook点,而对于这一点很多同学都会感觉到非常的困难,因为对于修改系统方法还好,因为可以简单的去查看具体的Android源码即可,但是如果说要去编写一些应用和游

  • Android微信抢红包功能的实现原理浅析

    快到过农历年了,微信红包也越来越多了,出现了好多红包外挂程序,就很好奇如何实现的,于是自己研究了一番,亲自写了个微信抢红包的APP.现在就一步一步来实现它. 实现思路 微信抢红包程序开启时候,他就可以随时识别.捕获红包,服务可以实现正在功能,当我们开启服务的时候,服务就不停的在后台运行,不停地轮询着微信里面的消息,当发现红包时候就立即打开微信红包所在的界面.但是他怎识别红包呢?需要找到微信抢红包里面节点的view,当找到对应的view,在获取view的关键字或者id,根据关键字或者id,自动的模

  • Android微信Tinker热更新详细使用

    先看一下效果图 Tinker已知问题 由于原理与系统限制,Tinker有以下已知问题: Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件: 由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码: 在Android N上,补丁对应用启动时间有轻微的影响: 不支持部分三星android-21机型,加载补丁时会主动抛出"TinkerRuntimeException:checkDexInstall failed": 由于各个厂商的

随机推荐