这次我们来使用AccessibilityService实现一个微信抢红包的辅助工具。
先来一个简单的效果图,最后会有一个完整的效果图:
首先,先回想一下微信红包的领取流程。
1.通知栏出现微信红包的消息
2.点击通知栏,进入领取红包界面
3.点击领取红包,领取成功后,进入拆红包界面
4.拆红包,显示获得金额
5.等待下一个红包
那么根据之前学到的关于AccessibilityService的知识可以这样填写配置文件:
<service
android:name="krelve.demo.rob.RobMoney"
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/rob_service_config" /></service>
AccessibilityService的相关配置 xml/rob_service_config:
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_description"
android:notificationTimeout="100"
android:packageNames="com.tencent.mm" />
由于我们这里只需要监听微信产生的事件,所以packageNames属性应当填写微信的包名。
下面便是最重要的抢红包代码:
package krelve.demo.rob;
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.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;public class RobMoney extends AccessibilityService {
@Override
public 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("[微信红包]")) {
// 监听到微信红包的notification,打开通知
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")) {
getPacket();// 领取红包
} else if (className
.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) {
openPacket();// 打开红包
}
break;
}
}@SuppressLint("NewApi")
private void openPacket() {
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if (nodeInfo != null) {
List<AccessibilityNodeInfo> list = nodeInfo
.findAccessibilityNodeInfosByText("拆红包");
for (AccessibilityNodeInfo n : list) {
n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}}
@SuppressLint("NewApi")
private void getPacket() {
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
if (rootNode != null) {
List<AccessibilityNodeInfo> nodeInfos = rootNode
.findAccessibilityNodeInfosByText("领取红包");
for (AccessibilityNodeInfo nodeInfo : nodeInfos) {
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}}
}@Override
public void onInterrupt() {}
}
在onAccessibilityEvent中,监听AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED和AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED事件。如果是通知栏事件,那么获取通知事件的text,如果包含 [微信红包] 字样,则说明是一个红包的通知事件。
然后通过event.getParcelableData()获取Notification实例对象,调用其中的pendingintent即可。
通知栏响应事件就是打开领取红包的界面,自己写了一个模拟微信红包的demo,来方便测试。
处理完通知栏事件后,就是窗体事件了。
进入领取红包界面后,如何找到领取红包的点击按钮并实现点击呢?
1.确定当前窗体界面是领取红包界面:event.getClassName().toString() 通过判断className来确定
2.AccessibilityNodeInfo 中有这样一个方法:findAccessibilityNodeInfosByText()
所以可以通过寻找 领取红包 字样来找到领取红包的点击事件。
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
if (rootNode != null) {
List<AccessibilityNodeInfo> nodeInfos = rootNode
.findAccessibilityNodeInfosByText("领取红包");
for (AccessibilityNodeInfo nodeInfo : nodeInfos) {
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}}
这样就可以实现领取红包的点击。
既然已经获得红包,那么就要拆红包了。
类似领红包,拆红包只是类名和搜索的text不一样而已:
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if (nodeInfo != null) {
List<AccessibilityNodeInfo> list = nodeInfo
.findAccessibilityNodeInfosByText("拆红包");
for (AccessibilityNodeInfo n : list) {
n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
这样就实现了一个最基本的抢红包辅助工具,剩下的细节可以慢慢实现。
最后看一下最终的效果图: