抢红包的原理都差不多,一般是用Android的辅助功能(AccessibilityService类)先监听通知栏事件或窗口变化事件来查找红包关键字然后去模拟点击或打开红包。
下面附上源码,程序已实现自动抢红包,锁屏黑屏状态自动解锁亮屏,Android4.X测试通过。函数具体功能请看详细注释。
注:在聊天界面收到红包不会自动打开,因为通知栏没有消息提示从而监听不了,此时只需手动点一下即可。其他未知情况请自行用LogCat调试,源码已经有相关的调试信息。软件仅供学习娱乐。
<pre style="margin-top: 0px; margin-bottom: 0px;"><span style="font-family: Arial, Helvetica, sans-serif; color: rgb(192, 192, 192);"></span><pre style="margin-top: 0px; margin-bottom: 0px;">import java.util.Calendar; import java.util.List; import android.accessibilityservice.AccessibilityService; import android.annotation.SuppressLint; import android.app.KeyguardManager; import android.app.KeyguardManager.KeyguardLock; import android.app.Notification; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; import android.content.Context; import android.media.MediaPlayer; import android.os.PowerManager; import android.util.Log; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.Toast; public class Demo extends AccessibilityService {private boolean canGet = false;//能否点击红包private boolean enableKeyguard = true;//默认有屏幕锁//窗口状态private static final int WINDOW_NONE = 0;private static final int WINDOW_LUCKYMONEY_RECEIVEUI = 1;private static final int WINDOW_LUCKYMONEY_DETAIL = 2;private static final int WINDOW_LAUNCHER = 3;private static final int WINDOW_OTHER = -1;//当前窗口private int mCurrentWindow = WINDOW_NONE;//锁屏、解锁相关private KeyguardManager km;private KeyguardLock kl;//唤醒屏幕相关private PowerManager pm;private PowerManager.WakeLock wl = null;//播放提示声音private MediaPlayer player;public void playSound(Context context) {Calendar cal = Calendar.getInstance();int hour = cal.get(Calendar.HOUR_OF_DAY);//夜间不播放提示音if(hour > 7 && hour < 22) { player.start();}}//唤醒屏幕和解锁private void wakeAndUnlock(boolean unLock){if(unLock){//若为黑屏状态则唤醒屏幕if(!pm.isScreenOn()) {//获取电源管理器对象,ACQUIRE_CAUSES_WAKEUP这个参数能从黑屏唤醒屏幕wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "bright");//点亮屏幕wl.acquire();Log.i("demo", "亮屏");}//若在锁屏界面则解锁直接跳过锁屏if(km.inKeyguardRestrictedInputMode()) {//设置解锁标志,以判断抢完红包能否锁屏enableKeyguard = false;//解锁kl.disableKeyguard();Log.i("demo", "解锁");}}else{//如果之前解过锁则加锁以恢复原样if(!enableKeyguard) {//锁屏kl.reenableKeyguard();Log.i("demo", "加锁");}//若之前唤醒过屏幕则释放之使屏幕不保持常亮if(wl != null) {wl.release();wl = null;Log.i("demo", "关灯");}}}//通过文本查找节点public AccessibilityNodeInfo findNodeInfosByText(AccessibilityNodeInfo nodeInfo, String text) {List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(text);if(list == null || list.isEmpty()) {return null;}return list.get(0);}//模拟点击事件public void performClick(AccessibilityNodeInfo nodeInfo) {if(nodeInfo == null) {return;}if(nodeInfo.isClickable()) {nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);} else {performClick(nodeInfo.getParent());}}//模拟返回事件public void performBack(AccessibilityService service) {if(service == null) {return;}service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);}//实现辅助功能@Override public void onAccessibilityEvent(AccessibilityEvent event) { int eventType = event.getEventType();Log.i("demo", Integer.toString(eventType));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("demo", "text:"+content);//收到红包提醒if (content.contains("[微信红包]")||content.contains("[QQ红包]")) { //模拟打开通知栏消息 if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {//播放提示音playSound(this);//若是微信红包则解锁并自动打开,若是qq红包则只提示并跳转到有红包的聊天界面,暂未实现qq红包自动领取功能if(content.contains("[微信红包]"))wakeAndUnlock(true);Log.i("demo", "canGet=true");canGet = true;try {Notification notification = (Notification) event.getParcelableData(); PendingIntent pendingIntent = notification.contentIntent; pendingIntent.send();} catch (CanceledException e) { e.printStackTrace(); }}break;} } } break;//第二步:监听是否进入微信红包消息界面 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:String className = event.getClassName().toString();if (className.equals("com.tencent.mm.ui.LauncherUI")) { mCurrentWindow = WINDOW_LAUNCHER;//开始抢红包 Log.i("demo", "准备抢红包...");getPacket();} else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) {mCurrentWindow = WINDOW_LUCKYMONEY_RECEIVEUI;//开始打开红包Log.i("demo", "打开红包");openPacket();wakeAndUnlock(false);} else if(className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")) {mCurrentWindow = WINDOW_LUCKYMONEY_DETAIL;//返回以方便下次收红包Log.i("demo", "返回");performBack(this);} else {mCurrentWindow = WINDOW_OTHER;}break;case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:if(mCurrentWindow != WINDOW_LAUNCHER) { //不在聊天界面或聊天列表,不处理return;}if(canGet) {getPacket();}break;}}//找到红包并点击@SuppressLint("NewApi") private void getPacket() { AccessibilityNodeInfo nodeInfo = getRootInActiveWindow(); if (nodeInfo == null) { return; }// 找到领取红包的点击事件 List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("领取红包");if(list != null ) {if(list.isEmpty()) {Log.i("demp", "领取列表为空");// 从消息列表查找红包AccessibilityNodeInfo node = findNodeInfosByText(nodeInfo, "[微信红包]");if(node != null) {canGet = true;performClick(node);}}else {if(canGet) {//最新的红包领起AccessibilityNodeInfo node = list.get(list.size() - 1);performClick(node);Log.i("demo", "canGet=false");canGet = false;}}}}//打开红包@SuppressLint("NewApi") private void openPacket() { AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if(nodeInfo == null) {return;}Log.i("demo", "查找打开按钮...");AccessibilityNodeInfo targetNode = null;//如果红包已经被抢完则直接返回targetNode = findNodeInfosByText(nodeInfo, "看看大家的手气");if(targetNode != null) {performBack(this);return;}//通过组件名查找开红包按钮,还可通过组件id直接查找但需要知道id且id容易随版本更新而变化,旧版微信还可直接搜“ ”字找到按钮if(targetNode == null) { Log.i("demo", "打开按钮中...");for (int i = 0; i < nodeInfo.getChildCount(); i++) {AccessibilityNodeInfo node = nodeInfo.getChild(i);if("android.widget.Button".equals(node.getClassName())) {targetNode = node;break;}}}//若查找到打开按钮则模拟点击if(targetNode != null) {final AccessibilityNodeInfo n = targetNode;performClick(n);} } @Overridepublic void onInterrupt() {Toast.makeText(this, "抢红包服务被中断啦~", Toast.LENGTH_LONG).show();}@Overrideprotected void onServiceConnected() {super.onServiceConnected();Log.i("demo", "开启");//获取电源管理器对象pm=(PowerManager)getSystemService(Context.POWER_SERVICE);//得到键盘锁管理器对象km= (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);//初始化一个键盘锁管理器对象kl = km.newKeyguardLock("unLock");//初始化音频player = MediaPlayer.create(this, R.raw.songtip_m);Toast.makeText(this, "_已开启抢红包服务_", Toast.LENGTH_LONG).show();}@Overridepublic void onDestroy() {super.onDestroy();Log.i("demo", "关闭");wakeAndUnlock(false);Toast.makeText(this, "_已关闭抢红包服务_", Toast.LENGTH_LONG).show();}}
AndroidManifest.xml中声明相关服务和权限
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <pre name="code" class="html"><service android:name="com.example.test.Demo" 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="@layout/accessibility_config"/></service></application>
accessibility_config.xml服务配置内容如下
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault" android:canRetrieveWindowContent="true" android:description="@string/desc" android:notificationTimeout="100" android:packageNames= "com.tencent.mm,com.tencent.mobileqq" />
其中description为辅助功能的描述内容,packageNames为监听的程序包名,此处只监听微信和QQ的accessibilityEventTypes
以上所述是针对Android辅助功能AccessibilityService与抢红包辅助的相关知识,希望对大家有所帮助。
新闻热点
疑难解答
图片精选