教你一步步实现Android微信自动抢红包
本文介绍微信自动抢红包的实现方法,主要实现以下几个功能
1.自动拆开屏幕上出现的红包
2.处于桌面或聊天列表时接收到红包信息时自动进入聊天界面并拆红包
3.日志功能,记录抢红包的详细日志
实现原理
1.利用AessibilityService辅助服务,监测屏幕内容,实现自动拆红包的目的。
2.利用ActiveAndroid数据库简单记录红包日志
3.利用preference实现监控选项纪录
最终界面
抢红包核心代码
AessibilityService配置
android:aessibilityEventTypes 设置触发监听回调的事件类型;
android:packageNames 设置监听的应用,这里监听的是微信,填上微信的包名.tencent.mm
在AndroidManifest.xml中声明:
抢红包实现代码
接收系统发送来的AessibilityEvent
private static final String GET_RED_PACKET = "领取红包";
private static final String CHECK_RED_PACKET = "查看红包";
private static final String RED_PACKET_PICKED = "手慢了,红包派完了";
private static final String RED_PACKET_PICKED2 = "手气";
private static final String RED_PACKET_PICKED_DETAIL = "红包详情";
private static final String RED_PACKET_SAVE = "已存入零钱";
private static final String RED_PACKET_NOTIFICATION = "[微信红包]";
@Override
public void onAessibilityEvent(AessibilityEvent event) {
L.d("RECEIVE EVENT!");
if (atchedFlags == null) return;
if (!mMutex) {
if (atchedFlags.get("pref_atch_notification") && atchNotifications(event)) return;
if (atchedFlags.get("pref_atch_list") && atchList(event)) return;
}
if (!atchedFlags.get("pref_atch_chat")) return;
this.rootNodeInfo = event.getSource();
if (rootNodeInfo == null) return;
mReceiveNode = null;
mUnpackNode = null;
checkNodeInfo();
if (mLuckyMoneyReceived && !mLuckyMoneyPicked && (mReceiveNode != null)) {
mMutex = true;
AessibilityNodeInfo cellNode = mReceiveNode;
cellNode.getParent().performAction(AessibilityNodeInfo.ACTION_CLICK);
mLuckyMoneyReceived = false;
mLuckyMoneyPicked = true;
L.d("正在打开!");
}
if (mNeedUnpack && (mUnpackNode != null)) {
AessibilityNodeInfo cellNode = mUnpackNode;
cellNode.performAction(AessibilityNodeInfo.ACTION_CLICK);
mNeedUnpack = false;
L.d("正在领取!");
}
if (mNeedBack) {
performGlobalAction(GLOBAL_ACTION_BACK);
mMutex = false;
mNeedBack = false;
L.d("正在返回!");
//总次数和金额统计
if (isGetMoney) {
T.shoShort(this, "抢到一个红包: " + gotMoney + "元!");
totalMoney = totalMoney + gotMoney;
totalSuessNum++;
myPrefs.totalMoney().put(totalMoney);
myPrefs.suessNum().put(totalSuessNum);
L.d("totalMoney: " + totalMoney);
L.d("totalSuessNum: " + totalSuessNum);
saveToLog(hongbaoInfo);
isGetMoney = false;
}
}
}
检测监听事件的节点信息
private void checkNodeInfo() {
L.d("checkNodeInfo!");
if (this.rootNodeInfo == null) return;
List nodes1 = this.findAessibilityNodeInfosByTexts(this.rootNodeInfo, ne String[]{
GET_RED_PACKET, CHECK_RED_PACKET});
if (!nodes1.isEmpty()) {
L.d("!nodes1.isEmpty()");
AessibilityNodeInfo targetNode = nodes1.get(nodes1.size() - 1);
if ("android.idget.LinearLayout".equals(targetNode.getParent().getClassName()))//避免被文字干扰导致外挂失效
{
if (this.signature.generateSignature(targetNode)) {
mLuckyMoneyReceived = true;
mReceiveNode = targetNode;
L.d("signature:" + this.signature.toString());
}
} else {
L.d("this is text");
}
return;
}
List nodes2 = this.findAessibilityNodeInfosByTexts(this.rootNodeInfo, ne String[]{
"拆红包"});
if (!nodes2.isEmpty()) {
L.d("node2 != null");
for (AessibilityNodeInfo nodeInfo : nodes2) {
if (nodeInfo.getClassName().equals("android.idget.Button"))
nodeInfo.performAction(AessibilityNodeInfo.ACTION_CLICK);
}
} else {
AessibilityNodeInfo node2 = (this.rootNodeInfo.getChildCount() > 3) ? this.rootNodeInfo.getChild(3) : null;
if (node2 != null && node2.getClassName().equals("android.idget.Button")) {
mUnpackNode = node2;
mNeedUnpack = true;
isToGetMoney = true;
L.d("find red packet!");
return;
}
}
if (mLuckyMoneyPicked) {
List nodes3 = this.findAessibilityNodeInfosByTexts(this.rootNodeInfo, ne String[]{
RED_PACKET_PICKED, RED_PACKET_SAVE, RED_PACKET_PICKED2, RED_PACKET_PICKED_DETAIL});
if (!nodes3.isEmpty()) {
L.d("!nodes3.isEmpty()");
if (rootNodeInfo.getChildCount() > 1) {
L.d("RED_PACKET_PICKED!");
} else {
L.d("nodes3.get(0).toString(): " + nodes3.get(0).getText().toString());
if (!nodes3.get(0).getText().toString().equals(RED_PACKET_PICKED_DETAIL)) {
AessibilityNodeInfo targetNode = nodes3.get(nodes3.size() - 1);
hongbaoInfo.getInfo(targetNode);
if (isToGetMoney) {
isGetMoney = true;
isToGetMoney = false;
gotMoney = hongbaoInfo.getMoney();
L.d("gotMoney: " + gotMoney);
}
L.d("RED_PACKET_SAVE!");
L.d("hongbaoInfo: " + hongbaoInfo.toString());
} else {
L.d("this packet is myself!");
}
}
mNeedBack = true;
mLuckyMoneyPicked = false;
}
}
}
主要通过检测“领取红包”等关键文字信息来判断是否有新红包
检测收到红包时判断是否"android.idget.LinearLayout",屏蔽聊天信息中的文字干扰
拆红包时,由于微信版本可能不同,进行两种判断,以兼容部分版本
拆完红包需自动返回,有以下几种情况抢到了,手慢了,以及该红包是自己发出的红包
下面是监听聊天列表的代码
private boolean atchList(AessibilityEvent event) {
// Not a message
if (event.getEventType() != AessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || event.getSource() == null)
return false;
List nodes = event.getSource().findAessibilityNodeInfosByText(RED_PACKET_NOTIFICATION);
if (!nodes.isEmpty()) {
AessibilityNodeInfo nodeToClick = nodes.get(0);
CharSequence contentDescription = nodeToClick.getContentDescription();
if (contentDescription != null && !lastContentDescription.equals(contentDescription)) {
nodeToClick.performAction(AessibilityNodeInfo.ACTION_CLICK);
lastContentDescription = contentDescription.toString();
return true;
}
}
return false;
}
下面是监听通知信息的代码
private boolean atchNotifications(AessibilityEvent event) {
// Not a notification
if (event.getEventType() != AessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)
return false;
// Not a hongbao
String tip = event.getText().toString();
if (!tip.contains(RED_PACKET_NOTIFICATION)) return true;
Parcelable parcelable = event.getParcelableData();
if (parcelable instanceof Notification) {
Notification notification = (Notification) parcelable;
try {
notification.contentIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
return true;
}
红包信息的获取,及日志的存储
通过获取节点的子信息,分别获得红包发送者及抢到的金额、抢红包时间等信息,建立简单的表单分别记录该信息。
@Table(name = "HongbaoInfos")
public class HongbaoInfo extends Model {
private int month;
private int day;
private int hour;
private int min;
private int sec;
@Column(name = "sender")
public String sender;
@Column(name = "money")
public String money;
@Column(name = "time")
public String time;
public void getInfo(AessibilityNodeInfo node) {
AessibilityNodeInfo hongbaoNode = node.getParent();
sender = hongbaoNode.getChild(0).getText().toString();
money = hongbaoNode.getChild(2).getText().toString();
time = getStringTime();
}
private String getStringTime() {
Calendar c = Calendar.getInstance();
month = c.get(Calendar.MONTH) + 1;
day = c.get(Calendar.DAY_OF_MONTH);
hour = c.get(Calendar.HOUR_OF_DAY);
min = c.get(Calendar.MINUTE);
sec = c.get(Calendar.SECOND);
return month+"月"+day+"日 "+hour+":"+min+":"+sec;
}
@Override
public String toString() {
return "HongbaoInfo [sender=" + sender + ", money=" + money + ", time=" + time + "]";
}
public static List getAll() {
return ne Select()
.from(HongbaoInfo.class)
.orderBy("Id ASC")
.execute();
}
public static void deleteALL() {
ne Delete().from(HongbaoInfo.class).execute();
}
public float getMoney() {
return Float.parseFloat(money);
}
public String getSender() {
return sender;
}
public String getTime() {
return time;
}
}
存储操作
private void saveToLog(HongbaoInfo hongbaoInfo) {
if (atchedFlags.get("pref_etc_log")) {
HongbaoInfo hongbaoInfo1 = ne HongbaoInfo();
hongbaoInfo1 = hongbaoInfo;
hongbaoInfo1.save();
} else {
L.d("log closed!");
}
}
主要的代码到这里基本结束,目前在微信最新版上测试ok,尚还存在以下几个问题
1.同一个人连续发的不能自动抢,因为为了防止重复点击做了过滤,同一个人的红包抢了后不会点击
2.AessibilityService开启时间长后有时会被系统关掉
结束语
空调维修
- 我的世界电脑版运行身份怎么弄出来(我的世界
- 空调抽湿是什么意思,设置抽湿的温度有什么意
- 方太燃气灶有一个打不着火 怎么修复与排查方法
- 夏季免费清洗汽车空调的宣传口号
- 清洗完空调后出现漏水现象
- iphone6能玩什么游戏(iphone6游戏)
- 如何设置电脑密码锁屏(如何设置电脑密码锁屏
- win10删除开机密码提示不符合密码策略要求
- 电脑w7显示不是正版(w7不是正版怎么解决)
- 万家乐z8热水器显示e7解决 怎么修复与排查方法
- 1匹空调多少瓦数(1匹空调多少瓦)
- 安卓手机连接电脑用什么软件好(关于安卓手机
- 电脑网页看视频卡是什么原因(爱拍看视频卡)
- 华帝燃气灶点火器一直响然后熄火怎么办:问题
- 电脑壁纸怎么换(关于电脑壁纸怎么换的介绍)
- 冬天空调的出风口应该朝什么方向(冬天空调风