利用AccessibilityService实现“微信红包”插件
16lz
2021-01-26
一、什么是AccessibilityService?
AccessibilityService是android的一个辅助服务抽象类,它是继承Service类,可以用于监听通知栏的变化、窗体改变、窗体内容改变、EditText光标移动、TextView内容改变等事件。
二、基本实现流程。
如下图:
三、主要代码段。
1、RedPacket类继承AccessibilityService,实现如下:
package com.nicksong.luckymoney;import java.io.IOException;import java.util.List;import android.accessibilityservice.AccessibilityService;import android.annotation.SuppressLint;import android.app.Notification;import android.app.PendingIntent;import android.app.PendingIntent.CanceledException;import android.content.res.AssetFileDescriptor;import android.content.res.AssetManager;import android.media.MediaPlayer;import android.util.Log;import android.view.accessibility.AccessibilityEvent;import android.view.accessibility.AccessibilityNodeInfo;public class RedPacket extends AccessibilityService {private MediaPlayer player;private boolean isFirst = false;@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {int eventType = event.getEventType();switch (eventType) {//第一步:监听通知栏消息case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:List texts = event.getText();if (!texts.isEmpty()) {for (CharSequence text : texts) {String content = text.toString();Log.i("demo", "text:"+content);if (content.contains("[微信红包]")) {isFirst = true;playSound4LuckyMoneyComing();//模拟打开通知栏消息if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {Notification notification = (Notification) event.getParcelableData();PendingIntent pendingIntent = notification.contentIntent;try {pendingIntent.send();} catch (CanceledException e) {e.printStackTrace();}}}}}break;//第二步:监听是否进入微信红包消息界面case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:String className = event.getClassName().toString();if (className.equals("com.tencent.mm.ui.LauncherUI")) {Log.i("demo", "开始抢红包");//开始抢红包getPacket();} else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) {Log.i("demo", "开始拆红包");isFirst = false;//开始打开红包openPacket();}//else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")) {//Log.i("demo", "在红包详情直接返回");////模拟点击返回//goBackFromLmUi();//}break;}}/** * 在红包详情界面模拟返回 */private void goBackFromLmUi() {isFirst = false;AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo != null) {for (int i = 0; i < nodeInfo.getChildCount(); i++) {Log.i("demo", "goBackFromLmUi i = " + i);Log.i("demo", "goBackFromLmUi Click"+",isClickable:" + nodeInfo.getChild(i).isClickable());Log.i("demo", "goBackFromLmUi View type = " + nodeInfo.getChild(i).getClassName());if ("android.widget.LinearLayout".equals(nodeInfo.getChild(i).getClassName()) && nodeInfo.getChild(i).isClickable()) {nodeInfo.getChild(i).performAction(AccessibilityNodeInfo.ACTION_CLICK);}}}}/** * 查找到 */@SuppressLint("NewApi")private void openPacket() {AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo != null) {for (int i = 0; i < nodeInfo.getChildCount(); i++) {Log.i("demo", "openPacket i = " + i);Log.i("demo", "Click"+",isClickable:" + nodeInfo.getChild(i).isClickable());Log.i("demo", "View type = " + nodeInfo.getChild(i).getClassName());if ("android.widget.Button".equals(nodeInfo.getChild(i).getClassName()) && nodeInfo.getChild(i).isClickable()) {nodeInfo.getChild(i).performAction(AccessibilityNodeInfo.ACTION_CLICK);}}}}@SuppressLint("NewApi")private void getPacket() {AccessibilityNodeInfo rootNode = getRootInActiveWindow();recycle(rootNode);}/** * 打印一个节点的结构 * @param info */@SuppressLint("NewApi")public void recycle(AccessibilityNodeInfo info) { if (info.getChildCount() == 0) { if(info.getText() != null){ if("领取红包".equals(info.getText().toString())){ //这里有一个问题需要注意,就是需要找到一个可以点击的View Log.i("demo", "Click"+",isClick:"+info.isClickable()); info.performAction(AccessibilityNodeInfo.ACTION_CLICK); AccessibilityNodeInfo parent = info.getParent(); while(parent != null){ Log.i("demo", "parent isClick:"+parent.isClickable()); if(parent.isClickable() && isFirst){ parent.performAction(AccessibilityNodeInfo.ACTION_CLICK); break; } parent = parent.getParent(); } } } } else { for (int i = 0; i < info.getChildCount(); i++) { if(info.getChild(i)!=null){ recycle(info.getChild(i)); } } } } @Overridepublic void onInterrupt() {}private void playSound4LuckyMoneyComing() {try {AssetManager assetManager = this.getAssets();AssetFileDescriptor aFileDescriptor = assetManager.openFd("luckymoney_sound.ogg");player = new MediaPlayer();player.setDataSource(aFileDescriptor.getFileDescriptor(), aFileDescriptor.getStartOffset(), aFileDescriptor.getLength());player.prepare();player.start();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
2、res/xml/accessibility.xml如下:
<?xml version="1.0" encoding="utf-8"?>
3、manifest清单文件主要部分如下:
四、“设置-辅助服务”打开“微信红包插件”服务。
不同的手机,这个辅助服务的名称、位置可能都不一样,这个就要大家在自己手机里找一下,应该很快能找到。如,魅族的一款手机,这个菜单位置如下截图:
五、源码。
https://github.com/Ericsongyl/WechatRedPacket
欢迎star、fork,并提出宝贵意见和建议。
注意:Android系统4.1以上、微信版本6.3.28及以上。
---------------------------------------------------------------------------------------------------------------
声明:请勿商用,否则后果由投入商用者本人承担!
更多相关文章
- tcping测试服务器TCP端口
- 使用AIDL实现进程间的通信
- 浅析Android(安卓)Service 中 onStartCommand方法及注意事项
- android如何得到控件大小 OnGlobalLayoutListener
- Android(安卓)Socket服务器 Servlet服务器
- smack 源码分析- PacketReader (android上实现长连接)【3】
- 【Android】BroadcastReceiver发送intent给service或者activity
- Android笔记——如何将软键盘的回车键改为搜索键
- Android(安卓)实现“再按一次退出程序”