阅读该文章前,可以先阅读我前两篇文章
微信自动回复和自动抢红包实现原理(一):AccessibilityService的介绍和配置
微信自动回复和自动抢红包实现原理(二):自动回复
经过前两篇文章的阅读,我相信大家应该对AccessibilityService有一定的了解了,是不是已经按捺不住,想自己动手试试?先别急,可以再看完我这篇文章还不迟,相信你另有收获的。接下来我们来探索一下自动抢红包的实现原理。
看了我第二篇微信自动回复文章的朋友应该知道怎么做了,只是一些操作上不同:
1. 监听TYPE_NOTIFICATION_STATE_CHANGED事件
2. 根据Notification打开会话人聊天界面
3. 搜索红包控件
4. 点击红包控件,打开红包,如果红包已被抢,跳至第6步,否则执行第5步
5. 点击红包界面的“开”按钮,抢红包
6. 返回微信主界面
好吧,我们给测试手机微信发个红包,先打印log来看看,具体信息不贴了,直接看结果:
打开微信的界面
-------------------------------------------------------------
PackageName:com.tencent.mm
Source Class:com.tencent.mm.ui.LauncherUI
Description:null
Event Type(int):32
-------------------------------------------------------------
红包接收界面(不管红包还没抢光还是已被抢光都会打开这个界面)
-------------------------------------------------------------
PackageName:com.tencent.mm
Source Class:com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI
Description:null
Event Type(int):32
-------------------------------------------------------------
红包详情界面(也就是抢到红包以后的界面)
-------------------------------------------------------------
PackageName:com.tencent.mm
Source Class:com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI
Description:null
Event Type(int):32
-------------------------------------------------------------
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
经我测试,LauncherUI只有微信在后台才会触发,但微信在前台时也会有Notification,所以有LuckyMoneyReceiveUI、LuckyMoneyDetailUI两个界面我们已经足够了
接下来的工作是找到相应的控件了。先找红包这个控件,给测试机微信发多几次红包,找到每个红包的相同点。
看到红色框框没,“领取红包”这个控件每次都不变了,可以根据其找到其父控件,再点击就可以打开红包了!
接下来就是红包界面的“开”按钮了。很遗憾,因为该按钮即每文本信息,也没特别的子控件,没办法,只能直接用控件的id了(但这种方法不好,因为据了解,控件的id经常会变,可能就会了防止这类插件的出现吧,哈哈),下面介绍如何获取控件的id。
1.打开DDMS,连接手机,打开一个红包,进入红包界面,点击下面按钮
2.选中你需要的控件,例如这里我们是要查看“开”按钮这控件
3.在右边就可以查看控件的信息了,右下方可以查看id
嗯,对的,红包的控件也可以这样获取,但我说过了,id是会变的,所以能不用就最好不要用。还有如果有朋友知道不用id获取“开”按钮的话,请告诉我一声哈。
好了,所有难点都解决了,接下来只要写代码处理下逻辑就好了,直接上代码吧。
**
* 自动抢红包服务
*/
public class AutoOpenLuckyMoneyService extends AccessibilityService{
private static final String TAG = AutoOpenLuckyMoneyService.class.getSimpleName();
private static final int MSG_BACK_HOME = 0;
private static final int MSG_BACK_ONCE = 1;
boolean hasNotify = false;
boolean hasLuckyMoney = true;
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
int eventType = event.getEventType(); // 事件类型
switch (eventType) {
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: // 通知栏事件
Log.i(TAG, "TYPE_NOTIFICATION_STATE_CHANGED");
if(PhoneController.isLockScreen(this)) { // 锁屏
PhoneController.wakeAndUnlockScreen(this); // 唤醒点亮屏幕
}
openAppByNotification(event); // 打开微信
hasNotify = true;
break;
default:
Log.i(TAG, "DEFAULT");
if(hasNotify) {
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
clickLuckyMoney(rootNode); // 点击红包
String className = event.getClassName().toString();
if (className.equals(UI.LUCKY_MONEY_RECEIVE_UI)) { //红包接收界面
if(!openLuckyMoney()) { // 如果红包被抢光了,就返回主界面
backToHome();
hasNotify = false;
}
hasLuckyMoney = true;
} else if (className.equals(UI.LUCKY_MONEY_DETAIL_UI)) { // 抢到红包
backToHome();
hasNotify = false;
hasLuckyMoney = true;
} else { // 处理没红包的情况,直接返回主界面
if(!hasLuckyMoney) {
handler.sendEmptyMessage(MSG_BACK_ONCE);
hasLuckyMoney = true; // 防止后退多次
}
}
}
break;
}
}
@Override
public void onInterrupt() {
}
/**
* 打开微信
* @param event 事件
*/
private void openAppByNotification(AccessibilityEvent event) {
if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
Notification notification = (Notification) event.getParcelableData();
try {
PendingIntent pendingIntent = notification.contentIntent;
pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
}
/**
* 搜索并点击红包
*/
private void clickLuckyMoney(AccessibilityNodeInfo rootNode) {
if(rootNode != null) {
int count = rootNode.getChildCount();
for (int i = count - 1; i >= 0; i--) { // 倒序查找最新的红包
AccessibilityNodeInfo node = rootNode.getChild(i);
if (node == null)
continue;
CharSequence text = node.getText();
if (text != null && text.toString().equals("领取红包")) {
AccessibilityNodeInfo parent = node.getParent();
while (parent != null) {
if (parent.isClickable()) {
parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
break;
}
parent = parent.getParent();
}
}
clickLuckyMoney(node);
}
}
}
/**
* 打开红包
*/
private boolean openLuckyMoney() {
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
if(rootNode != null) {
List<AccessibilityNodeInfo> nodes =
rootNode.findAccessibilityNodeInfosByViewId(UI.OPEN_LUCKY_MONEY_BUTTON_ID);
for(AccessibilityNodeInfo node : nodes) {
if(node.isClickable()) {
Log.i(TAG, "open LuckyMoney");
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
return true;
}
}
}
return false;
}
private void backToHome() {
if(handler.hasMessages(MSG_BACK_HOME)) {
handler.removeMessages(MSG_BACK_HOME);
}
handler.sendEmptyMessage(MSG_BACK_HOME);
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(msg.what == MSG_BACK_HOME) {
performGlobalAction(GLOBAL_ACTION_BACK);
postDelayed(new Runnable() {
@Override
public void run() {
performGlobalAction(GLOBAL_ACTION_BACK);
hasLuckyMoney = false;
}
}, 1500);
} else if(msg.what == MSG_BACK_ONCE) {
postDelayed(new Runnable() {
@Override
public void run() {
Log.i(TAG, "click back");
performGlobalAction(GLOBAL_ACTION_BACK);
hasLuckyMoney = false;
hasNotify = false;
}
}, 1500);
}
}
};
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
ok,到这里就全部讲完了,小伙伴们可以自己去实现更多更有趣、更新奇的功能了。这里我只是作为技术探索,容我再啰嗦两点:
1. 朋友是很重要的,有空的话还是好好回复吧
2. 红包只是一种噱头,一种娱乐方式,别当作谋财之道喔