首先附上参考大全:
Android中微信抢红包插件原理解析和开发实现
Android用AccessibilityService 辅助服务实现微信抢红包APP
CodeBoy微信抢红包外挂

抢红包的原理都差不多,一般是用Android的辅助功能(AccessibilityService类)先监听通知栏事件或窗口变化事件来查找红包关键字然后去模拟点击或打开红包。


下面附上源码,程序已实现自动抢红包,锁屏黑屏状态自动解锁亮屏,Android4.X测试通过。函数具体功能请看详细注释。

注:在聊天界面收到红包不会自动打开,因为通知栏没有消息提示从而监听不了,此时只需手动点一下即可。其他未知情况请自行用LogCat调试,源码已经有相关的调试信息。软件仅供学习娱乐。

<pre name="code" class="java">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);        }       }         @Override    public void onInterrupt() {        Toast.makeText(this, "抢红包服务被中断啦~", Toast.LENGTH_LONG).show();    }    @Override    protected 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();    }        @Override    public void onDestroy() {    super.onDestroy();    Log.i("demo", "关闭");        wakeAndUnlock(false);        Toast.makeText(this, "_已关闭抢红包服务_", Toast.LENGTH_LONG).show();    }}
  

AndroidManifest.xml中声明相关服务和权限

<pre name="code" class="html"><pre name="code" class="html"><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" ><serviceandroid: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



更多相关文章

  1. Android自适应不同屏幕几种方法
  2. Android屏幕完美适配最全攻略(最权威的官方适配指导)
  3. Android的Activity屏幕切换动画(二)-左右滑动深入与实战
  4. [置顶] Android的Activity屏幕切换动画(二)-左右滑动深入与实战
  5. Android获取手机屏幕的宽高
  6. android之Display.getRotation()_传感器控制屏幕旋转
  7. 转化屏幕•ViewFlipper 的使用

随机推荐

  1. android studio真机调试offline的问题
  2. Android数据库编程教程
  3. [android]Context 上下文
  4. android完全退出程序的方法
  5. android Handler导致内存泄露分析
  6. Android数据通信——JSON&Gson(Android(
  7. Android图片压缩-大小与质量压缩
  8. Android入门之TabHost,TabWidget
  9. cocox2d-x在android下崩溃log的定位
  10. android TextView ellipsize 只显示一个