微信,QQ抢红包软件原理解析
2016-01-28 23:16
621 查看
微信,QQ抢红包软件原理解析
目前市面上的抢红包软件都仅限于监听通知栏确定红包到来模拟点击红包,对于停留在qq聊天界面不能起作用,并且对于Android5.0,6,0版本更高的安全限制以及无法正常抢到红包。本博客将介绍真正的抢红包软件,无论停留在qq消息界面,还是qq在后台运行,均可以完美抢到红包,并且支持口令红包,以及口令消息的自动撤回功能。同时还将实现红包消息到来时聊天窗口的自动切换功能,并且对Android5.0,6,0更高级别的安全限制做了适配。抢红包的原理主要利用Android中的辅助功能,不懂的可以自行百度也可参考博文 /article/2095678.html 来模拟点击,类似于按键精灵。
监听红包消息有两种,一种是通过监听通知栏(适用于退出qq,微信后台运行的情况,另一种是通过监听视图的变化(适用于停留在当前聊天界面的情况)
话不多说,直接贴关键代码:
代码块
/** * Created by 张建浩 on 15-11-6. */ public class GetMoneyService extends AccessibilityService { private final static String TAG = GetMoneyService.class.getName(); private Timer timer; private final static int PACKET_MM = 0; private final static int PACKET_QQ = 1; private boolean autoClick = false; private boolean autoClick2 = false; private boolean autoClickNotification = false; private int qqCommandPacketLock = 0; private int messageRevocation = 0; private int messageRevocation2 = 0; private String revocationMessage = null; private int inputMessageFlag = 0; private boolean canRevocation = false; //可信度 private int confidenceLevel = 0; private int protectQQCommandLock = 0; private boolean willDeleteMessage = false; private boolean needCallbackMessage = false; public String getCurrentActivity(){ if (android.os.Build.VERSION.SDK_INT<21){ ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> runningTasks = manager .getRunningTasks(1); ActivityManager.RunningTaskInfo cinfo = runningTasks.get(0); ComponentName component = cinfo.topActivity; return component.getClassName(); } else if (android.os.Build.VERSION.SDK_INT<23) { return getCurrentPkgName(this); } else return getProcessNew(); } private String getProcessNew() { String topPackageName = null; UsageStatsManager usage = (UsageStatsManager)getSystemService(Context.USAGE_STATS_SERVICE); long time = System.currentTimeMillis(); List<UsageStats> stats = usage.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time); if (stats != null) { SortedMap<Long, UsageStats> runningTask = new TreeMap<Long,UsageStats>(); for (UsageStats usageStats : stats) { runningTask.put(usageStats.getLastTimeUsed(), usageStats); } if (runningTask.isEmpty()) { // Log.v(TAG,"running tast is empty"); return null; } topPackageName = runningTask.get(runningTask.lastKey()).getPackageName(); } return topPackageName; } public String getCurrentPkgName(Context context) { ActivityManager.RunningAppProcessInfo currentInfo = null; Field field = null; int START_TASK_TO_FRONT = 2; String pkgName = null; try { field = ActivityManager.RunningAppProcessInfo.class.getDeclaredField("processState"); } catch (Exception e) { e.printStackTrace(); } ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> appList = am.getRunningAppProcesses(); for (ActivityManager.RunningAppProcessInfo app:appList) { if (app.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { Integer state = null; try { state = field.getInt( app ); } catch (Exception e) { e.printStackTrace(); } if (state != null && state == START_TASK_TO_FRONT) { currentInfo = app; break; } } } if (currentInfo != null) { pkgName = currentInfo.processName; } return pkgName; // ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE); // // List<ActivityManager.RunningAppProcessInfo> tasks = manager.getRunningAppProcesses(); // // Log.i(TAG,"current_app"+tasks.get(0).processName); // return tasks.get(0).processName; } @Override protected void onServiceConnected() { super.onServiceConnected(); Log.v(TAG, "服务已连接"); AccessibilityServiceInfo info = getServiceInfo(); info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN; info.packageNames = new String[]{"com.tencent.mm", "com.tencent.mobileqq"}; setServiceInfo(info); qqCommandPacketLock = 0; needCallbackMessage = SharePreferenceUtils.getBooleanValue(getApplicationContext(),"message","can_callback_message"); // Log.v(TAG,"need callback:"+needCallbackMessage); // timer = new Timer(); // timer.schedule(new TimerTask() { // @Override // public void run() { // Log.v(TAG,"current acitivity:"+getCurrentActivity()); // } // },0,2000); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { int eventType = event.getEventType(); confidenceLevel = 0; canRevocation = false; Log.v(TAG,"回调了"); switch (eventType) { //第一步:监听通知栏消息 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: List<CharSequence> texts = event.getText(); if (!texts.isEmpty()) { for (CharSequence text : texts) { String content = text.toString(); Log.i(TAG, "text:"+content); if (content.contains(Constant.MM_LUCKY_MONEY)||content.contains(Constant.QQ_LUCKY_MONEY)) { //模拟打开通知栏消息 if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) { Notification notification = (Notification) event.getParcelableData(); PendingIntent pendingIntent = notification.contentIntent; try { String currentApp = getCurrentActivity(); if (currentApp != null && currentApp.matches("com.\\w+launcher\\w+")){ } autoClickNotification = true; pendingIntent.send(); } catch (Exception e) { e.printStackTrace(); } } } } } break; //第二步:监听是否进入红包消息界面 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: String className = event.getClassName().toString(); Log.v(TAG,"class name:"+className); switch (className){ case "com.tencent.mm.ui.LauncherUI": //开始抢红包 Log.v(TAG,"开始寻找微信红包"); if (autoClickNotification) getPacket(PACKET_MM); break; case "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI": //开始打开红包 // Log.v(TAG,"准备打开微信红包啦"); openPacket(); break; case "com.tencent.mobileqq.activity.SplashActivity": // Log.v(TAG,"开始进入qq界面"); qqCommandPacketLock = 0; recycle(getRootInActiveWindow(),Constant.QQ_LUCKY_MONEY); getPacket(PACKET_QQ); break; case "cooperation.qwallet.plugin.QWalletPluginProxyActivity": qqCommandPacketLock = 0; if (messageRevocation == 1) messageRevocation ++; Log.v(TAG,"出现了窗口"); if (autoClick) { performGlobalAction(GLOBAL_ACTION_BACK); autoClick = false; if (autoClickNotification) { performGlobalAction(GLOBAL_ACTION_HOME); // performGlobalAction(GLOBAL_ACTION_RECENTS); autoClickNotification = false; } } break; } break; case AccessibilityEvent.TYPE_VIEW_SCROLLED: // if ("com.tencent.mm.ui.LauncherUI".contains(getCurrentActivity())) // getPacket(PACKET_MM); // else if ("com.tencent.mobileqq.activity.SplashActivity".contains(getCurrentActivity())){ // getPacket(PACKET_QQ); // } break; default: Log.v(TAG,"content update:"+getCurrentActivity()); String currentActivity = getCurrentActivity(); // getPacket(PACKET_QQ); // getPacket(PACKET_MM); // Log.v (TAG,"current contain:"+(currentActivity!= null&¤tActivity.contains("com.tencent.mobileqq.activity"))); // if ("com.tencent.mm.ui.LauncherUI".contains(currentActivity)) { // getPacket(PACKET_MM); // } if ("com.tencent.mobileqq.activity.SplashActivity".contains(currentActivity)||(currentActivity!= null&¤tActivity.contains("com.tencent.mobileqq.activity"))){ getPacket(PACKET_QQ); } break; } } /** * 查找到 */ private void openPacket() { AccessibilityNodeInfo nodeInfo = getRootInActiveWindow(); if (nodeInfo != null) { autoClickNotification = false; recycle(nodeInfo, Constant.MM_GET_PACKET); } } private void getPacket(int type) { AccessibilityNodeInfo rootNode = getRootInActiveWindow(); if (type == PACKET_MM) recycle(rootNode, Constant.MM_LUCKY_MONEY2); else if (type == PACKET_QQ) recycle(rootNode,Constant.QQ_GET_PACKET); } private void recycle(AccessibilityNodeInfo info,String keywords) { if (info != null){ if (info.getChildCount() == 0) { if(info.getText() != null){ Log.v(TAG,"qqcommandLock:"+qqCommandPacketLock+"protectlock"+protectQQCommandLock); Log.v(TAG,info.getText().toString()); String uitext = info.getText().toString(); if (inputMessageFlag == 1){ // Log.v(TAG,"获取到输入的文本3:"+uitext); revocationMessage = uitext; inputMessageFlag = 0; } if (uitext.equals(getString(R.string.copy))||uitext.equals(getString(R.string.forward))||uitext.equals(getString(R.string.collect))||uitext.equals(getString(R.string.delete))){ //识别关键字可信度 confidenceLevel++; // Log.v(TAG,"confidence:"+confidenceLevel); } if (needCallbackMessage&&uitext.equals(getString(R.string.delete))){ //可信度大于等于3并且不可撤回, if (confidenceLevel>=3 && !canRevocation&& messageRevocation2 >= 1){ // performGlobalAction(GLOBAL_ACTION_BACK); messageRevocation2++; info.performAction(AccessibilityNodeInfo.ACTION_CLICK); } else if (messageRevocation2 >=2){ messageRevocation2 = 0; autoClickNodeInfo(info); } // Log.v(TAG,"messageRevocaton2:"+messageRevocation2+" confidence:"+confidenceLevel+"canrevocation"+canRevocation); //是删除并且要删除信息 } if(keywords.equals(info.getText().toString())){ //这里有一个问题需要注意,就是需要找到一个可以点击的View Log.i("demo", "Click" + ",isClick:" + info.isClickable()); autoClick = true; autoClickNodeInfo(info); }else if (uitext.contains(Constant.QQ_LUCKY_MONEY) && !uitext.equals(Constant.QQ_LUCKY_MONEY)){ autoClickNodeInfo(info); }else if ((qqCommandPacketLock ==0&& Constant.QQ_COMMAND_PACKET.equals(info.getText().toString()))){ //点击拆开 qqCommandPacketLock = 1; protectQQCommandLock = 0;//防止死锁变量 autoClick = true; autoClickNodeInfo(info); }else if (qqCommandPacketLock == 1&&Constant.QQ_PACKET_COMMAND_INPUT.equals(uitext)){ qqCommandPacketLock = 2; inputMessageFlag = 1; protectQQCommandLock = 1; autoClick = true; autoClickNodeInfo(info); }else if (qqCommandPacketLock == 2 && getString(R.string.send).equals(info.getText().toString())){ qqCommandPacketLock = 0; protectQQCommandLock = 0; messageRevocation = 1; autoClick = true; autoClickNodeInfo(info); }else if (messageRevocation >1&&info.getText().toString().equals(revocationMessage)){ if (needCallbackMessage){ messageRevocation2 ++; info.performAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); } }else if (messageRevocation >=1&&getString(R.string.revocation).equals(uitext)){ if (needCallbackMessage){ canRevocation = true; messageRevocation = -1; info.performAction(AccessibilityNodeInfo.ACTION_CLICK); } }else if (messageRevocation <0 && getString(R.string.confirm).equals(info.getText().toString())){ messageRevocation = 0; info.performAction(AccessibilityNodeInfo.ACTION_CLICK); } } } else { for (int i = 0; i < info.getChildCount(); i++) { if(info.getChild(i)!=null){ recycle(info.getChild(i),keywords); } } } } } private void autoClickNodeInfo(AccessibilityNodeInfo info) { autoClick = true; if (info.isClickable()) info.performAction(AccessibilityNodeInfo.ACTION_CLICK); else { AccessibilityNodeInfo parent = info.getParent(); while(parent != null){ // Log.i("demo", "parent isClick:"+parent.isClickable()); if(parent.isClickable()){ autoClick = true; parent.performAction(AccessibilityNodeInfo.ACTION_CLICK); break; } parent = parent.getParent(); } } } @Override public void onInterrupt() { if (timer != null){ timer.cancel(); timer = null; } } } /** * Created by 张建浩 on 15-11-6. */ public class Constant { public final static String MM_LUCKY_MONEY = "[微信红包]"; public final static String MM_LUCKY_MONEY2 = "微信红包"; public final static String MM_GET_PACKET = "拆红包"; public final static String QQ_LUCKY_MONEY = "[QQ红包]"; public final static String QQ_GET_PACKET = "点击拆开"; public final static String QQ_COMMAND_PACKET = "口令红包"; public final static String QQ_PACKET_COMMAND_INPUT = "点击输入口令"; }
代码比较多,这里只贴了抢红包服务的关键代码,读者可自行修改。软件下载地址:http://download.csdn.net/detail/u013454746/9421612
相关文章推荐
- Fibonacci数列小程序
- 《微信力量》:微信公众号应用成功案例集,三星推荐
- 微信企业号开发(6)--发送消息
- java利用微信企业号将位置信息推送到普通微信号并在微信中直接查看地图位置
- 服务器数据抓包(原来微信图片真的可以抓包看的)
- 微信oauth2.0和自定义菜单携带openid
- Javaweb project Servlet类回调微信企业号
- Android微信、朋友圈分享回调函数无响应
- intellj 创建Servlet小程序
- 如何写一个自动抢微信红包的程序
- 初试微信订阅号有感
- 微信公众平台开发(数据库连接)
- java微信二次开发01
- 微信朋友圈图片处理策略
- c#版在pc端发起微信扫码支付
- 夺命雷公狗---微信开发13----获取access_token
- 关于微信的分享功能
- 微信红包照片的揭秘
- 微信公众号被动回复两条消息(一条正常,一条暂无法提供服务)
- 微信java开发之实现微信主动推送消息