Android之微信抢红包实现原理分析

原创 2016年08月28日 20:57:52

微信抢红包主要用到AccessibilityService,该服务需要用户手动到辅助功能里面授权,下面直接粘贴源码,先看Activity,主要是跳转到辅助功能界面,让用户开启辅助功能的服务:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        View btn = findViewById(R.id.open_help_btn);
        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(
                        android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
                startActivity(intent);
            }
        });
    }

}

下面看服务的使用,需要配置相关参数,如:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_description"
    android:notificationTimeout="100"
    android:packageNames="com.tencent.mm" />

再看服务的声明:

<service
    android:name="com.yongfei.hongbao.AccService"
    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="@xml/service_config" />
</service>

最后看抢红包功能的实现:

public class AccService extends AccessibilityService {

    private static final String NOTIFICATION_HONGBAO = "[微信红包]";
    private static final String HONGBAO_MSG = "微信红包";
    private static final String LAUNCHER_UI = "com.tencent.mm.ui.LauncherUI";
    private static final String OPEN_MONEY_UI = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI";
    private static final String OPEN_ID = "com.tencent.mm:id/ba_";
    private boolean mIsFromNotification = false;
    // 标记在微信主界面时收到红包消息
    private boolean mIsMsgWindow = true;
    private WakeLock mWakeLock;
    private KeyguardManager mKeyguardManager;
    private KeyguardLock mKeyguardLock;
    private boolean mIsOperationLock = false;

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        if (eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
            List<CharSequence> text = event.getText();
            if (!text.isEmpty()) {
                for (CharSequence item : text) {
                    String t = String.valueOf(item);
                    System.out.println("zyf通知内容:" + t);
                    if (t.contains(NOTIFICATION_HONGBAO)) {
                        mIsFromNotification = true;
                        mIsMsgWindow = true;
                        if (isKeyguardLocked()) {
                            wakeAndUnlock(true);
                        }
                        openNotification(event);
                        break;
                    }
                }
            }
        } else if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            mIsMsgWindow = false;
            // 只有从通知栏进入聊天界面的才点击红包消息/拆红包
            // 因为拆完红包返回时也会引起窗口变化
            if (mIsFromNotification) {
                windowStateChanged(event);
                return;
            }
            // 聊天界面手动点击红包消息时,自动拆包
            if (OPEN_MONEY_UI.equals(event.getClassName())) {
                // 拆红包界面,点击拆红包
                openHongBao();
            }
        }
    }

    private void wakeAndUnlock(boolean unlock) {
        if (unlock) {
            PowerManager manager = (PowerManager) getSystemService(Context.POWER_SERVICE);
            mWakeLock = manager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP
                    | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "money");
            mWakeLock.acquire();
            if (mKeyguardManager != null) {
                mKeyguardLock = mKeyguardManager.newKeyguardLock("unLock");
                mKeyguardLock.disableKeyguard();
                mIsOperationLock = true;
            }
        } else {
            if (mKeyguardLock != null) {
                mKeyguardLock.reenableKeyguard();
                mIsOperationLock = false;
            }
            if (mWakeLock != null) {
                mWakeLock.release();
            }
        }
    }

    private boolean isKeyguardLocked() {
        mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        return mKeyguardManager.isKeyguardLocked();
    }

    /**
     * 界面变化
     * 
     * @param event
     */
    private void windowStateChanged(AccessibilityEvent event) {
        if (LAUNCHER_UI.equals(event.getClassName())) {
            // 主界面或聊天界面,点击红包消息
            clickHongBaoMsg();
        } else if (OPEN_MONEY_UI.equals(event.getClassName())) {
            // 拆红包界面,点击拆红包
            openHongBao();
        }
    }

    /**
     * 拆红包
     */
    private void openHongBao() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            System.out.println("zyf openHongBao is null");
            return;
        }
        // 抢别人发的红包
        List<AccessibilityNodeInfo> openId = nodeInfo
                .findAccessibilityNodeInfosByViewId(OPEN_ID);
        if (openId != null && openId.size() > 0) {
            openId.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }if (mIsOperationLock) { wakeAndUnlock(false); }
        // 抢没抢到红包都要把变量赋为false,以便后续继续拆从通知栏进来的红包消息
        mIsFromNotification = false;

    }

    /**
     * 点击红包消息
     */
    private void clickHongBaoMsg() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            System.out.println("zyf rootwindow is null");
            return;
        }
        List<AccessibilityNodeInfo> list = nodeInfo
                .findAccessibilityNodeInfosByText(HONGBAO_MSG);
        if (list.size() >= 1) {
            // 只拆最后一个红包
            AccessibilityNodeInfo item = list.get(list.size() - 1);
            AccessibilityNodeInfo parent = item.getParent();
            parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
    }

    /**
     * 打开通知栏消息
     * 
     * @param event
     */
    private void openNotification(AccessibilityEvent event) {
        if (event.getParcelableData() == null
                || !(event.getParcelableData() instanceof Notification)) {
            return;
        }

        // 获取通知栏的意图并打开
        Notification notification = (Notification) event.getParcelableData();
        PendingIntent pendingIntent = notification.contentIntent;
        try {
            pendingIntent.send();
            // 只有接收到通知并且窗口没有变化时才需要点击红包消息
            // 因为此时是在微信主界面
            if (mIsMsgWindow) {
                clickHongBaoMsg();
            }
        } catch (CanceledException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onInterrupt() {
        System.out.println("zyf 服务中断了");
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        System.out.println("zyf 服务连接成功");
    }

}

由于上面用到wakelock和解锁/锁屏功能,故需要在配置文件中添加相关权限:

<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>

另外,需要把apk加入到各种白名单,因为应用被杀后辅助功能会自动收回该应用的授权。

另外,手机静音时该服务是不可用的。

附apk下载链接

上面代码是基于微信6.3.23版本实现的,不同版本id可能会不同。

Android中微信抢红包插件原理解析和开发实现

自从去年中微信添加抢红包的功能,微信的电商之旅开启。但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导致了。或许是网络的原因,而且这...
  • jiangwei0910410003
  • jiangwei0910410003
  • 2015年10月04日 22:14
  • 79902

Android进阶——学习AccessibilityService实现微信抢红包插件

  • 2016年11月21日 13:55
  • 23.82MB
  • 下载

Android实现微信自动抢红包的程序

简单实现了微信自动抢红包的服务,原理就是根据关键字找到相应的View, 然后自动点击。主要是用到AccessibilityService这个辅助服务,基本可以满足自动抢红包的功能,但是有些逻辑需要优化...
  • shineflowers
  • shineflowers
  • 2015年07月28日 18:31
  • 22868

Android红包效果

  • 2016年08月19日 10:04
  • 943KB
  • 下载

微信红包实现原理

微信红包实现原理 以下内容来源于QCon某高可用架构群聊天记录整理 背景:有某个朋友咨询微信红包的架构,在官方或非官方同学的解释和讨论中得出以下讨论内容,在此期间有多个同学发红包做现网算法测试。 ...
  • ws891033655
  • ws891033655
  • 2015年05月05日 14:37
  • 2906

android抢红包代码解析支持微信与QQ

最近有一段时间没写博客了,一方面是工作比较忙,一方面也着实本人水平有限,没有太多能与大家分享的东西,也就是在最近公司要做一个抢红包的功能,老板发话了咋们就开干呗,本人就开始在网上收集资料,经过整理和实...
  • zero_zero_zero_zero
  • zero_zero_zero_zero
  • 2016年07月24日 00:25
  • 6144

用自定义view实现一个抢红包的demo

快过年了,给大家一个抢红包的demo吧,redbag实现了移动、旋转、透明度3种渐变效果,设置活动时效为1分钟,会越来越快...
  • zj695469296
  • zj695469296
  • 2016年01月25日 18:18
  • 1866

Android抢红包源码

  • 2015年02月27日 11:53
  • 5.13MB
  • 下载

Android AccessibilityService实现微信自动抢红包

转至:http://blog.csdn.net/jwzhangjie/article/details/47205299 最近要实现微信自动抢红包的功能,使用AccessibilityService来...
  • h183288132
  • h183288132
  • 2016年03月24日 16:58
  • 4216

Android进阶——学习AccessibilityService实现微信抢红包插件

前言 在你的手机更多设置或者高级设置中,我们会发现有个无障碍的功能,很多人不知道这个功能具体是干嘛的,其实这个功能是为了增强用户界面以帮助残障人士,或者可能暂时无法与设备充分交互的人们 它的具...
  • qq_30379689
  • qq_30379689
  • 2016年11月21日 14:03
  • 12025
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android之微信抢红包实现原理分析
举报原因:
原因补充:

(最多只允许输入30个字)