新的一年又到了,又到了拼手速和网速的时候了,网速是硬件条件,没有办法了,不过手速这种东西,没有还不能创造么,哈哈。其实之前网上有很多老铁已经分享过类似的插件的实现方式,但是微信其实本身也是在做对第三方插件的规避操作,所以,微信的每一个新版本都会修改相同控件的id,所以之前的很多插件都不能再使用了,而且之前的有些判断方法也不能再适用新版本的微信,所以我研究了几天,新版全自动微信抢红包助手就应运而生了,老规矩,给大家看下效果。

全自动抢红包无非也就是写个逻辑代替你手动点击的过程,要实现这个功能,就要用到Android提供的无障碍服务(AccessibilityService)的功能。辅助功能可以得到系统级别的事件和服务,通过这些事件和服务,我们就能监控微信的红包消息,不过第三方应用的辅助功能都需要手动开启。

关于AccessibilityService的使用,简单的介绍下,不做过多的介绍,简单的分成三部:

第一步:自定义一个服务继承自AccessibilityService,重写对应的方法

package com.cretin.www.redpacketplugin.services;import android.accessibilityservice.AccessibilityService;import android.annotation.TargetApi;import android.os.Build;import android.view.accessibility.AccessibilityEvent;/** * Created by cretin on 2018/2/9. */public class RedPackageService extends AccessibilityService { @Override public void onCreate() { super.onCreate(); } @Override protected void onServiceConnected() { //系统成功连接到辅助功能服务时调用 super.onServiceConnected(); } @TargetApi( Build.VERSION_CODES.JELLY_BEAN_MR2 ) @Override public void onAccessibilityEvent(AccessibilityEvent event) { //当系统检测到与Accessibility服务指定的事件过滤参数 // 匹配的AccessibilityEvent时调用 } @Override public void onInterrupt() { //当系统想要中断服务提供的反馈时调用 } @Override public void onDestroy() { super.onDestroy(); //当系统即将关闭辅助功能服务时调用 }}

第二步:给辅助服务书写配置文件

对属性做一个简单的解释

accessibilityEventTypes:响应那种类型的事件

accessibilityFeedbackType:设置回馈给用户的方式,有语音播出和振动

notificationTimeout:响应时间

packageNames:指定响应哪个应用的事件。这里填的是微信的包名,如果不填则是响应所有的应用事件

description:辅助服务的描述信息,会显示在无障碍服务的描述那里。

第三步:注册服务

属性的简单说明

//辅助功能的名称android:label="@string/accessibility_service_label" //此处必须声明一次权限android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" //指定配置文件的名字和位置android:name="android.accessibilityservice"android:resource="@xml/accessibility_service_config"

做好上面的准备工作后,我们就可以在onAccessibilityEvent(AccessibilityEvent event)方法中写我们具体的逻辑了。

看过之前老铁的处理方式是对AccessibilityEvent中getEventType来判断是所有类型,经过实验这种方式是不可靠的,经过多次测试,最终我觉得用getEventType只判断是否是通知栏事件比较靠谱。

if ( event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED ) { //通知栏事件} else { //非通知栏事件 处理其他事件}三、对非通知栏事件做细分处理

因为通知栏事件比较简单,直接点击通知栏就好了,点击通知栏后会自己跳转到聊天页面,剩下的事情也是交给对非通知栏事件来处理。

那么现在需要考虑的事情有以下几点:

微信自带抢红包功能 【为生活开发系列之二】Android微信新版全自动抢红包助手

然后,在搜索栏中输入自动抢红包神器,下载该APP。

越狱--最好 iPhone 5s iOS9.0 以下,(5c 32 位,从5s 开始 64 位的,便宜经济实惠,iOS 10以上可能会不完美越狱)。

此时会弹出此软件开启有效的页面,在开启有效页面里我们将抢红包开启有效点亮。这样手机设置就设置好了

第一:如何获取我们希望处理的控件并操控它。

第二:如何判断当前在哪个页面,是聊天列表页面,是聊天页面,是打开红包的页面还是打开红包后的详情页面。

第三:在不同的页面我们需要做什么事情,点击哪个控件。

获取一个有文本的控件有两种方式,一种是根据文本找控件,一种是根据id找控件,对于没有文本的控件,就使用id找控件。找到控件之后可以对控件主动触发一定的事件,比如最常用的点击事件。

//获取整个窗口根节点AccessibilityNodeInfo nodeInfo = getService().getRootInActiveWindow();//根据id获取所有使用这个id的控件节点集合List idNodes = nodeInfo.findAccessibilityNodeInfosByViewId(VIEW_ID_RECEIVE_BTN_OPEN);//根据内容获取所有这个有这个文本的控件节点集合List list = nodeInfo.findAccessibilityNodeInfosByText(TEXT_LINGQUHONGBAO);//对控件主动触发事件(这里触发的是点击事件,其他事件类型可自行研究 AccessibilityNodeInfo)if(!idNodes.isEmpty()){ idNodes.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);}

?问题:那么图和获取控件的id呢?

找到uiautomatorviewer后点击运行。

按如下操作就可以获取到控件id(记得插上手机或开启模拟器,手机或模拟器开启调试模式)

就目前来看,我们需要区分聊天列表页面(就是微信的首页),聊天页面(包括私信和群聊天),点击红包后的红包页面(这里包括两种情况,一种是红包还没有被别人抢,点“开”按钮会进入到详情页面,还有一种是红包被别人抢了,此时点击“开”出现的是“手慢了,红包派完了”的页面)和开红包后的详情页面。

看过之前老铁判断首页的方式是判断className,因为回到首页的时候className是com.tencent.mm.ui.LauncherUI(这个值也不是永恒不变的,要根据微信版本来),但是经过多次测试,当不在微信首页,在其他页面的时候,也会触发这个className,所以不靠谱。

后来经过多次测试,发现获取首页listview的item列表项的id,这个id只会在首页聊天列表页面出现,所以我就按照这个方式来确定当前页面是不是首页。

List listItemNodes = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/apr");if ( listItemNodes.isEmpty() ) { //反正不是在首页 不理会 return;} else { //在首页}

其实判断在哪个页面,最主要的就是找其他页面没有的特征控件,比如在聊天页面中,右下角那个“+”按钮才是最独特的,所以可以根据是否有这个按钮来判断是否是聊天页面。但是这个只能判断是否是聊天页面,不能判断是私信页面还是群聊页面。在对比了私信和群聊的页面之后,没有找到特别稳的方式来判断聊天类型,只能根据标题来判断,群聊的标题后面一定会有一个括号,括号里面是群成员人数。所以我们只需要来判断标题最后是否有一个括号里面是数字,当然这种方式不是特别准,不过够用了,一般用户也不会这个起昵称,万一这样起了也只是判断类型出错,也不会影响抢红包的功能。

List chatNodes = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/aak"); if ( chatNodes.isEmpty() ) { //不在聊天页面 不好说在哪儿}else{ //在聊天页面 List titleNodes = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/ha"); if ( titleNodes.isEmpty() ) { //无法判断类型 } else { //判断标题最后是否是一个括号,括号中是数字,当然最好是用正则 String title = titleNodes.get(0).getText().toString(); if ( !TextUtils.isEmpty(title) ) { if ( title.contains("(") ) { int indexLeft = title.lastIndexOf("("); String end = title.substring(indexLeft); end = end.substring(1, end.length() - 1); try { Integer.parseInt(end); //群聊 } catch ( Exception e ) { //私聊 } } else { //私聊 默认私聊 } } }}

还记得之前提到过的className吗,打开红包和红包详情页面就可以用这个了,别问我为什么知道啥时候用className,啥时候自己判断控件,这都是几十次调试和实验得到的。%>_= 0; i-- ) { AccessibilityNodeInfo node = list.get(i); AccessibilityNodeInfo parent = node.getParent(); if ( parent != null ) { List wxhbNodes = parent.findAccessibilityNodeInfosByViewId(VIEW_ID_HOME_LV_ITEM_LABEL_WXHB); if ( !wxhbNodes.isEmpty() ) { if ( TEXT_LV_ITEM_TIPS.equals(wxhbNodes.get(0).getText()) ) { //是的 没错 领取红包 AccessibilityHelper.performClick(node); return; } } } } }

基本上有了上面这些踩坑的经历,一个红包助手的架子基本也就齐全了。自己再加一些逻辑上的判断和功能上的私人订制,一个过年的工具就诞生了。

由于微信每个版本对于同一个控件的id都会做改变,所以,我们需要对不同的微信版本做适配,否则在使用过程中可能会出现意想不到的问题。以下是我整理的微信不同版本的我们所需要的控件的id的汇总,您看着是密密麻麻,我整理起来也是很辛苦的,小小心意,祝大家新年快乐。

最上面提供的动态图是我给周围朋友做的一个全自动红包插件,由于项目中有后台接口,是为了动态加载一些配置文件,让app体验更好,免得每次微信有新版本都要更新app,而且加了很多其他方面的判断,比较复杂,所以源码就不再放出来了。相信经过上面的分析,自己撸一个也不困难。

自动抢红包微信 索赔5000万元后看还有谁敢用

密码:wj1w(微信版本 6.7.3-同步微信更新)

在很多地方都用了 MMTableView;

如果我们想要知道我们抢了多少红包,可以在软件的设置首页里点击红包记录,来查找我们抢了多少红包,红包的来源及时间。