玩转Android之手摸手教你DIY一个抢红包神器!
AccessibilityService是Google专门为残障人士设计的一个服务,可以让他们更方便的来操作手机。AccessibilityService一个主要功能是通过监听窗口的变化来判断用户当前正在做什么,它可以监听到窗口焦点的变化,Activity的跳转,Activity中View的变化等等,通过监听窗口的这些变化我们来猜测用户正在做什么,从而模拟出一些操作。很早的时候,一些应用市场想要实现App的静默安装必须获取root权限,但是获取手机的root权限谈何容易?Google从Android6.0开始加强了root权限的管理,意味着Android6.0之后想要获取root权限将变得更加困难,于是有的应用市场,比如豌豆荚最早推出了免root自动升级或者安装应用的功能,豌豆荚就是利用这个AccessibilityService来实现的,当我们安装App的时候,系统都会弹出安装确认框,AccessibilityService看到安装二字的时候就去自动模拟点击这个按钮,从而实现免root应用的安装升级;AccessibilityService的另一个使用场景就是我们今天要说了抢红包神器啦!
Google为残障人士设计的AccessibilityService被天朝的程序员们玩坏了!
1.设计思路
先来说说实现思路吧,这个其实很简单,首先微信抢红包的过程可以分为两部分,第一步就是红包来了抢红包,第二步就是拆红包,我们的自动抢红包就是根据这两个步骤来实现。我们通过AccessibilityService来监测手机屏幕的变化,当发现有“领取红包”红包字样的时候,就点击该控件,从而进入到拆红包的页面,在该页面再获取拆红包的按钮,然后模拟点击该按钮,从而将money收入囊中,OK,这就是我们的一个整体思路。这里边有一个稍微麻烦的问题,就是怎样判断一个红包是否已经被抢过了,因为微信红包中抢过和没抢过的红包是一模一样的,所以很难从表面上进行区分,考虑到微信的聊天页面是使用ListView来实现的,每一条消息实际就是ListView中的一个item,所以这里我打算记录下当前页面所有红包消息的hashCode,同时又考虑到item会复用,即即将显示的item有可能是刚刚回收的item,这会导致hashCode重复,于是我采用一个HashSet来记录当前页面所有拆开红包的hashCode,每当要抢一个红包的时候,我都先判断该红包的hashCode是否已经存在于HashSet中,如果存在说明该红包已拆开,否则说明红包没被拆开过,此时将红包拆开,同时将该红包的hashCode存入hashSet中。另外,我还需要监测当前页面第一个红包的HashCode,如果第一个红包滑出当前页面,则将其对应的hashCode从HashSet中移除。OK,这就是整体思路。关于如何记录已拆开的红包,如果小伙伴们有更好的方式欢迎留言讨论。
2.编码实现
这里的代码也不难,整体上三个步骤:
1.自定义类继承自AccessibilityService,在该类中实现抢红包的逻辑代码
2.xml中对自定义的AccessibilityService进行配置
3.清单文件中配置服务
OK,我们就根据上面的三个步骤来实现抢红包吧。
1.定义RedPacketsAccessibilityService
public class RedPacketsAccessibilityService extends AccessibilityService { private Set<Integer> currentScreenRedPackets = new HashSet<>(); private int lastFirstVisiableRedPackets; @Override public void onCreate() { super.onCreate(); Notification.Builder builder = new Notification.Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher).setContentTitle("红包神器运行中"); startForeground(1, builder.build()); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (event.getSource() != null) { AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow(); if (rootInActiveWindow != null) { if (event.getEventType()==AccessibilityEvent.TYPE_VIEW_SCROLLED) { //抢红包 List<AccessibilityNodeInfo> list = rootInActiveWindow.findAccessibilityNodeInfosByText("领取红包"); if (list != null && list.size() > 0) { AccessibilityNodeInfo firstNode = list.get(0); if (lastFirstVisiableRedPackets != firstNode.hashCode()) { currentScreenRedPackets.remove(lastFirstVisiableRedPackets); lastFirstVisiableRedPackets = firstNode.hashCode(); } for (int i = list.size() - 1; i > -1; i--) { AccessibilityNodeInfo nodeInfo = list.get(i); if (!currentScreenRedPackets.contains(nodeInfo.hashCode())) { AccessibilityNodeInfo parent = nodeInfo.getParent(); if (parent != null) { parent.performAction(AccessibilityNodeInfo.ACTION_CLICK); currentScreenRedPackets.add(nodeInfo.hashCode()); break; } } } } } //拆红包 List<AccessibilityNodeInfo> nodeInfoList = rootInActiveWindow.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/bdg"); if (nodeInfoList != null && nodeInfoList.size() > 0) { for (AccessibilityNodeInfo accessibilityNodeInfo : nodeInfoList) { accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK); } } } } } @Override public void onInterrupt() { } }
AccessibilityService的使用我就不必多说了吧,这里我就简单说一下抢红包的过程,进入到onAccessbilityEvent方法中之后,如果该方法是由页面滚动触发的,则进入抢红包的逻辑判断,抢红包的时候,先来获取当前页面所有包含’领取红包‘字样的所有控件,然后遍历该控件,判断hashSet中是否有该控件的hashCode,有的话就拆红包。
2.xml中进行配置
在res目录下新建一个xml文件夹,在里边创建一个xml配置文件,这个配置现在也可以放在AccessbilityService的onCreate方法中执行:
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault" android:canRetrieveWindowContent="true" android:description="@string/app_name" android:notificationTimeout="100" />
accessibilityEventTypes表示要监听屏幕的哪些事件,typeAllMask表示监听所有事件,比如屏幕滚动,页面跳转等。android:accessibilityFeedbackType表示设置反馈方式,feedbackGeneric表示通用反馈模式。其他属性见名知意,不再赘述。
3.清单文件中配置服务
凡是服务,都需要在清单文件中进行配置,AccessibilityService也不例外,配置方式如下:
<service android:name=".RedPacketsAccessibilityService" android:enabled="true" android:label="红包神器" 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_config"/> </service>
注意metadata中配置的resource指向第二步创建的xml文件。OK,这样就可以了。
3.其他
有的小伙伴疑惑我怎么知道微信中页面结构等等信息,其实很简单,利用SDK中提供的uiautomatorviewer工具即可,在sdk的tools目录下,使用如下图:
OK,关于微信红包神器的介绍我们就说这么多,有问题欢迎留言讨论。
项目开源地址https://github.com/lenve/RedPackets
欢迎小伙伴们star、fork,pr。
App下载地址http://pan.baidu.com/s/1bBGaBW
以上。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?