欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

android拆轮子系列之一步一步教你写微信抢红包插件

发布时间:2023/12/20 35 豆豆
生活随笔 收集整理的这篇文章主要介绍了 android拆轮子系列之一步一步教你写微信抢红包插件 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

上一章《AccessibilityService讲解》我们对AccessibilityService做了基本的讲解,本章我们就利用AccessibilityService做一个抢红包插件。

1.前言

本章编写的代码仅供个人学习使用,禁止用于其他非法行为。技术是把双刃剑希望大家正确对待!

在文章的开头奉送上代码,方便大家对照着学习。

2.代码编写

2.1抢包流程:

做抢红包的插件我们得一步一步来,首先我们应该了解抢红包的流程是怎么样的,回顾一下抢红包的流程:

1. 状态栏出现”[微信红包]”的消息提示,点击进入聊天界面 2. 点击相应的红包信息,弹出抢红包界面 3. 在抢红包界面点击”开”,打开红包 4. 在红包详情页面,查看详情,点击返回按钮返回微信聊天界面.

上面就是抢红包的整个流程。虽然这是整个流程,但是当前微信处于的界面可能出现以下几种:

1.微信在后台运行,而当前手机在浏览其他APP(需要执行1->2->3->4) 2.当前处于微信的首页(需要执行1->2->3->4) 3.处于和某个人聊天的页面(2->3->4)

2.1代码编写

理解了抢红包的流程,我们开始编写代码。上一节讲了,创建一个AccessibilityService的流程很简单如下:
1.继承AccessibilityService类,重写里面的方法
2.在AndroidMainifest中注册
3.添加配置文件

1.下面我们来看一下AccessibilityService的编写

package com.czh.service; import java.util.ArrayList; import java.util.List; import android.accessibilityservice.AccessibilityService; import android.app.Notification; import android.app.PendingIntent; import android.content.Intent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.Toast;/*** @author 作者 YYD* @version 创建时间:2016年12月14日 下午2:46:49* @function 未添加*/ public class RobService extends AccessibilityService {/*** 此方法用来接收我的需要的各种事件 在accessibility.xml中我们监听了以下事件:* typeNotificationStateChanged typeWindowStateChanged* typeWindowContentChanged* http://www.jianshu.com/p/ba298b8d5a6e 看看这个是否被拆了判断*/@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {int eventType = event.getEventType();switch (eventType) {// 当通知栏发生改变的时候case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:List<CharSequence> texts = event.getText();if (!texts.isEmpty()) {for (CharSequence text : texts) {String content = text.toString();if (content.contains("[微信红包]")) {if ((event.getParcelableData() != null)&& (event.getParcelableData() instanceof Notification)) {Notification notification = (Notification) event.getParcelableData();PendingIntent pendingIntent = notification.contentIntent;try {pendingIntent.send();} catch (Exception e) {}}}}}break;// 当窗口内容发生改变的时候case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:break;// 当窗口状态发生改变的时候case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:String className = event.getClassName().toString();if (className.equals("com.tencent.mm.ui.LauncherUI")) { //聊天页 // getLastPacket();//注释的原因我在方法中写明了,如果放开这个方法就会出现死循环,大家可以尝试一下。 // inputClick("com.tencent.mm:id/fz");//这条语句是聊天页面返回键的id,放不放开都没用。} else if (className //拆红包页,点击“开”,抢红包.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) {inputClick("com.tencent.mm:id/bg7");} else if (className //红包详情页,点击返回键.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")) {inputClick("com.tencent.mm:id/gd");}break;}}/*** 根据id,获取AccessibilityNodeInfo,并点击。*/private void inputClick(String clickId) {AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo != null) {List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(clickId);for (AccessibilityNodeInfo item : list) {item.performAction(AccessibilityNodeInfo.ACTION_CLICK);}}} /*** 这个方法有缺陷。要是能加 过滤已拆红包就好了。我实在想不出好的办法所以注释掉了。* 如果大家有好的过滤方案,请告诉我一声,不胜感激!这是我的一个遗憾* 因为这一行注释掉,就不是我们想要的全自动的抢红包了。*/private void getLastPacket() {AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();recycle(nodeInfo);if (parents.size() > 0) {parents.get(parents.size() - 1).performAction(AccessibilityNodeInfo.ACTION_CLICK);}}@Overridepublic void onInterrupt() {}@Overrideprotected void onServiceConnected() {super.onServiceConnected();Toast.makeText(RobService.this, "成功与微信绑定,开始监听", Toast.LENGTH_SHORT).show();}ArrayList<AccessibilityNodeInfo> parents = new ArrayList<AccessibilityNodeInfo>(); /*** 这个方法是用递归的方式,遍历节点树。* 如果找到“领取红包”和“查看红包”所在叶子节点,就用while不断的找自己父节点,这个父节点要求可以被点击。(也是是说找最近一个可以点击的父节点)*/private void recycle(AccessibilityNodeInfo info) {if (info.getChildCount() == 0) {if (info.getText() != null) {if ("领取红包".equals(info.getText().toString())||"查看红包".equals(info.getText().toString())) { // if (info.isClickable()) { // info.performAction(AccessibilityNodeInfo.ACTION_CLICK); // }AccessibilityNodeInfo parent = info.getParent();while (parent != null) {if (parent.isClickable()) {parents.add(parent);//找到了添加到列表并推出循环,否则继续往上找父节点。break;}parent = parent.getParent();}}}} else {for (int i = 0; i < info.getChildCount(); i++) {if (info.getChild(i) != null) {recycle(info.getChild(i));}}}}@Overridepublic boolean onUnbind(Intent intent) {Toast.makeText(this, "断开与微信绑定,停止监听", Toast.LENGTH_SHORT).show();return super.onUnbind(intent);} }

这里我们对一些语句做一些解释:

1.getRootInActiveWindow(); //获取当前窗口的根节点。 2.findAccessibilityNodeInfosByViewId//根据id获取节点,获取的是一个列表 3.AccessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);//模拟点击事件 4.AccessibilityNodeInfo.getParent()获取父节点

2.MainActivity类的编写

public class MainActivity extends Activity implements OnClickListener{private Button settingBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findView();}private void findView(){settingBtn = (Button) findViewById(R.id.settingBtn);settingBtn.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch(v.getId()){case R.id.settingBtn://跳转到辅助设置页Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);startActivity(intent);break;}} }

3.看一下menifest中的注册

<service android:name="com.czh.service.RobService"android:enabled="true"android:exported="true"android:label="@string/servicelable"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>

这里对menifest讲解一下:

android:label="@string/servicelable"是服务描述

效果如下:

<serviceandroid:name="com.czh.service.RobService"android:enabled="true"android:exported="true"android:label="@string/servicelable"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" ><intent-filter><action android:name="android.accessibilityservice.AccessibilityService" /></intent-filter></service>

这一块是固定的写法,没什么好说的。注意权限是必须要加上!

<meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility" />

meta-data是配置文件,配置信息在accessibility.xml中

3.看一下accessibility.xml文件
在res文件夹下面新建一个文件夹xml –> 在xml文件夹中新建一个accessibility.xml文件。

<?xml version="1.0" encoding="utf-8"?> <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:notificationTimeout="100"android:description="@string/description"android:packageNames="com.tencent.mm" />

对这个accessibility.xml讲解一下:

1.android:accessibilityEventTypes 表示监听的事件类型,这本章中我们监听通知,屏幕状态变化,屏幕内容变化。typeAllMask表示监听所有类型 2.android:accessibilityFeedbackType 表示手机用什么方式将信息反馈给用户,语音震动等等,这里默认; 3.android:canRetrieveWindowContent="true",允许检索窗口内容,这一条必须要加上。 4.android:description 描述 5.android:packageNames="com.tencent.mm"这里我们监听微信的包名,如果你想监听多个App的话可以这样写: android:packageNames="com.tencent.mm|com.tencent.qq"

在配置文件中android:description添加后的效果图是这样的:

3.看一下strings.xml文件

<?xml version="1.0" encoding="utf-8"?> <resources><string name="app_name">微信抢红包</string><string name="servicelable">微信自动抢红包</string><string name="description">本插件仅供娱乐,切勿用于不当用途,出现问题后果自负!</string> </resources>

3.补充

大家可能在想,findAccessibilityNodeInfosByViewId()方法中的ID是如何知道的呢?下面我们就来解释一下:
在devices中有这么一个按钮,点击进入,效果图如下:

进入之后你会看到下面界面:

通过图你可以看出,左面是界面,又面是布局和控件的详细信息(我们可以通过这个来学习人家的布局规律),当你点击某个控件的时候,右面就会显示该控件的信息,图中我们标记出来了。

4.不足之处

我在写这个东西上时候有一个bug,一直不知道如何解决:新版微信无法区分未拆红包和已拆红包。就是因为这个原因程序会把已拆红包当成未拆红包来拆,导致死循环,如果有知道解决方案的朋友请告知我,不胜感激!

5.结尾

在文章的结尾奉送上代码,方便大家对照着学习。

在技术上我依旧是个小渣渣,加油勉励自己。

总结

以上是生活随笔为你收集整理的android拆轮子系列之一步一步教你写微信抢红包插件的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。