原理

我们使用的还是安卓自带的辅助功能 AccessibilityService 。
先来讲述以下原理,原理很简单,当页面发生变化的时候,搜索屏幕中的关键字,搜索到了就点开。这个原理在微信旧版本的自动抢红包是有效的,但是在新版本中,开红包的界面没办法这么做了,那我们需要自己模拟点击动作,从而点开这个红包。
AccessibilityService 在 SDK24 (即Android 7.0) 引入了一个方法 dispatchGesture ,从而使我们可以不用 root 就能模拟点击动作。所以在 app/build.gradle 中我们将最小的 SDK 版本设置为 24( minSdkVersion 24),所以如果你的安卓手机系统小于安卓 7.0,那就没办法使用我这个抢红包方法了。

onAccessibilityEvent

在辅助功能里面开启服务之后,onAccessibilityEvent 会接受到一些事件。

public void onAccessibilityEvent(AccessibilityEvent event) {
}

通过 event.getEventType() 就能获得当前界面的事件是什么。常用的事件如下。

事件 作用
TYPES_ALL_MASK 所有事件
TYPE_NOTIFICATION_STATE_CHANGED 通知栏事件
TYPE_VIEW_CLICKED 点击事件
TYPE_VIEW_FOCUSED 获取焦点事件
TYPE_VIEW_LONG_CLICKED 长按事件
TYPE_VIEW_SCROLLED 页面变动事件
TYPE_VIEW_SELECTED 控件选中
TYPE_VIEW_TEXT_CHANGED 输入框文本改变
TYPE_VIEW_TEXT_SELECTION_CHANGED 输入框文本 selection 改变
TYPE_WINDOW_CONTENT_CHANGED 窗口内容改变
TYPE_WINDOW_STATE_CHANGED 窗口状态改变

所以我们用到的其中的四个 TYPE_NOTIFICATION_STATE_CHANGED、TYPE_WINDOW_STATE_CHANGED、TYPE_VIEW_SCROLLED、TYPE_WINDOW_CONTENT_CHANGED。

创建 Service

package sms.example.com.automatic.service;import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.app.Notification;
import android.app.PendingIntent;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Handler;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;import java.util.List;import sms.example.com.automatic.utils.ScreenUtils;public class WeChetService extends AccessibilityService {private static final String TAG = "WeChetService";private static final String ENVELOPE_TEXT_KEY = "[微信红包]";private static final String WECHET_PACKAGE_NAME = "com.tencent.mm";private static final String WECHET_LAUCHER = "com.tencent.mm.ui.LauncherUI";private static final String LUCKEY_MONEY_RECEIVER = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI";private static final String LUCKEY_MONEY_DETAIL = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI";private Handler handler = new Handler();private CharSequence mClassName = "";@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {final int eventType = event.getEventType();switch (eventType) {case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:List<CharSequence> texts = event.getText();if (!texts.isEmpty()) {for (CharSequence t : texts) {String text = String.valueOf(t);Log.d(TAG, "监控微信消息==" + text);if (text.contains(ENVELOPE_TEXT_KEY)) {openNotification(event);break;}}}break;case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:openEnvelope(event);break;case AccessibilityEvent.TYPE_VIEW_SCROLLED:case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:openEnvelopeContent(event);break;default:break;}}/*** 打开通知栏* @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();} catch (PendingIntent.CanceledException e) {e.printStackTrace();}}private void openEnvelope(AccessibilityEvent event) {CharSequence className = event.getClassName();CharSequence packageName = event.getPackageName();boolean isWechetPage = WECHET_PACKAGE_NAME.equals(packageName);if(!isWechetPage) {return;}if (className.toString().contains(WECHET_PACKAGE_NAME)) {mClassName = className;}Log.i("openEnvelope", event.getClassName() + "");if (WECHET_LAUCHER.equals(className)) {findRedPacket();} else if (LUCKEY_MONEY_RECEIVER.equals(className)) {openRedPacket();} else if (LUCKEY_MONEY_DETAIL.equals(className)) {handler.postDelayed(new Runnable() {@Overridepublic void run() {clickBackKey();}}, 300);// Toast.makeText(this, "红包已经抢完--------", Toast.LENGTH_SHORT).show();}}private void openEnvelopeContent(AccessibilityEvent event) {Log.i("openEnvelopeContent", mClassName + "");if (mClassName.equals(WECHET_LAUCHER)) {findRedPacket();}}/*** 寻找领取红包关键字,找到之后点击打开*/private void findRedPacket() {AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo == null) {return;}List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("领取红包");if (list.isEmpty()) {return;}for (AccessibilityNodeInfo info : list) {AccessibilityNodeInfo parent = info.getParent();if (parent != null) {parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);break;}}}/*** 打开红包,加延时是因为红包界面出现会有延时* x 表示开字相对屏幕所在的横坐标, y 表示开字相对屏幕所在的纵坐标,不同手机会有不一样*/private void openRedPacket() {final int x = ScreenUtils.getWindowsWidth(WeChetService.this) / 2;final int y = 1200;handler.postDelayed(new Runnable() {@Overridepublic void run() {dispatchGestureView(x, y);}}, 300);}/*** 模拟点击事件* @param x 横坐标* @param y 纵坐标*/private void dispatchGestureView(int x, int y) {Point position = new Point(x, y);GestureDescription.Builder builder = new GestureDescription.Builder();Path p = new Path();p.moveTo(position.x, position.y);builder.addStroke(new GestureDescription.StrokeDescription(p, 0L, 500L));GestureDescription gesture = builder.build();dispatchGesture(gesture, new GestureResultCallback() {@Overridepublic void onCompleted(GestureDescription gestureDescription) {super.onCompleted(gestureDescription);Log.d(TAG, "onCompleted: 完成..........");}@Overridepublic void onCancelled(GestureDescription gestureDescription) {super.onCancelled(gestureDescription);Log.d(TAG, "onCompleted: 取消..........");}}, null);}@Overridepublic void onInterrupt() {Toast.makeText(this, "微信抢红包服务已关闭", Toast.LENGTH_SHORT).show();}@Overrideprotected void onServiceConnected() {super.onServiceConnected();Toast.makeText(this, "微信抢红包服务已开启", Toast.LENGTH_SHORT).show();}/*** 模拟返回键*/private void clickBackKey() {performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);}@Overridepublic void onDestroy() {super.onDestroy();}
}

ScreenUtils

package sms.example.com.automatic.utils;import android.app.Activity;
import android.content.Context;
import android.view.WindowManager;public class ScreenUtils {/*** 获得屏幕的宽度* @param context* @return*/public static int getWindowsWidth(Context context) {return context.getResources().getDisplayMetrics().widthPixels;}/*** 获得屏幕的高度*/public static int getWindowsHeight(Context context) {return context.getResources().getDisplayMetrics().heightPixels;}
}

创建对应的 xml

res/xml/text_server_config.xml

<?xml version="1.0" encoding="utf-8"?>
<accessibility-servicexmlns:android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeAllMask"android:accessibilityFeedbackType="feedbackGeneric"android:accessibilityFlags="flagDefault"android:canRetrieveWindowContent="true"android:description="@string/accessibility_description"android:notificationTimeout="10"android:canPerformGestures="true">
</accessibility-service>

上面的属性 description 是在手机系统无障碍中显示的内容。
res/values/strings.xml

<resources><string name="app_name">抢红包</string><string name="accessibility_description">自助抢红包</string>
</resources>

AndroidManifest.xml 注册

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="sms.example.com.automatic"><applicationandroid:name=".application.app"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><service android:name=".service.WeChetService"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"android:label="@string/accessibility_description"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService" /></intent-filter><meta-dataandroid:name="android.accessibilityservice"android:resource="@xml/text_server_config"/></service></application>
</manifest>

判断服务是否开启

    public static boolean isStartAccessibilityService(Context context, String name) {AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);List<AccessibilityServiceInfo> serviceInfos = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);for (AccessibilityServiceInfo info : serviceInfos) {String id = info.getId();if (id.contains(name)) {return true;}}return false;}private void isWeChetServiceOpen() {String weChetServiceName = ".service.WeChetService";boolean isWeChetServiceOpen = isStartAccessibilityService(this, weChetServiceName);if (isWeChetServiceOpen) {} else {}}

开启服务

    private void jumpToSettingPage() {Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);startActivity(intent);}

作者:yuzhiyi_宇
链接:https://www.jianshu.com/p/d9ec1e377892

Android 实现自动抢微信红包相关推荐

  1. python自动抢_Python+Appium实现自动抢微信红包

    前言 过年的时候总是少不了红包,不知从何时开始微信红包横空出世,对于网速和手速慢的人只能在一旁观望,做为python的学习者就是要运用编程解决生活和工作上的事情. 于是我用python解决我们的手速问 ...

  2. 如何写一个自动抢微信红包的程序

    春节临近,为避免错失土豪们的红包,动手写了一个自动抢微信红包的小程序,试了一下效果还不错.本程序适用于安卓4.1版本以上手机,不需要ROOT权限.现将程序的设计要点记录如下,供有兴趣的同行参考. 一. ...

  3. 我用Python自动抢微信红包!

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取 python免费学习资 ...

  4. android实现自动抢红包,Android手机辅助功能实现自动抢微信红包功能

    这个东西就算是纯粹的Android开发者也很少用,功能就相当于Xposed,但它是Android自带的服务,目的在于帮助那些具有视觉.身体或年龄相关限制的用户更轻松的使用Android设备和应用,它一 ...

  5. python自动抢微信红包源码_用Python实现微信自动化抢红包,再也不用担心抢不到红包了...

    1. 概述 刚刚收到了两个消息,一个好消息,一个坏消息. 先说好消息,好消息就是微信群里有人要发红包,开心~ 不过转念一想,前几次的红包一个都没抢到,这次???不由自主的叹了一口气 ... 过了一会, ...

  6. 爱钱博主私欲之作:Python+Appium实现自动抢微信红包

    对于抢红包我真的最爱啦,每次看见红包,心里那个激动颤抖,但因为工作原因难免没注意就没了啊,为了满足自己的私欲,就有了这篇文章的出现,爱钱博主私欲之作. 1.环境准备: appium环境 安卓手机 us ...

  7. 用 Python 来全自动抢微信红包

    最近在做手机app自动化测试,想用python写个自动抢微信红包的程序,先在网上查了一下,发现抢红包教程要么是用itchat模块做到红包提醒功能,要么root手机后用Xposed框架,这两种方式都不是 ...

  8. Android通过辅助功能实现抢微信红包原理简单介绍

    简书文章:https://www.jianshu.com/p/e1099a94b979 附抢红包开源项目地址,代码已全改为Kotlin了,已适配到最新微信7.0.5版本,如果对你有所帮助赏个star吧 ...

  9. python图片裁剪对比_Python自动抢视频红包,仅供学习!

    本文来源于公众号: AirPython 1 目 标 场 景 如今短视频横行的时代,以某短视频为首的,背后依靠着强大的资金后盾,疯狂地对平台用户进行红包轰炸. 与传统的红包不一样,视频红包包含位置的不确 ...

最新文章

  1. appcan 上/下拉刷新函数的一个简单封装
  2. java代码如何能运行起来_Java代码如何运行
  3. Android消息处理系统——Looper、Handler、Thread(转载)
  4. shell怎么把负数变成正数_excel怎么计算平方根-记住简单的收藏复杂的
  5. php 5.3.3 46.el6 6,centos php 5.3升级到 php5.4版本
  6. Jlink-v8 灯不亮重新烧写固件的办法
  7. 银行不放款算买房人违约吗?
  8. socket是什么?
  9. 百度文库的内容怎么复制
  10. c语言 自适应模式算术编码,算术压缩论文基于算术编码的数据压缩算法研究与实现.doc...
  11. 2. HTTP 报文
  12. 2020最新教师资格证《中学综合素质》必考知识点大全
  13. 优动漫PAINT实用宝典(图层篇)——栅格图层
  14. Regular Expression 正则表达式 语法规则及使用
  15. Win10应用商店提示0x80070422解决方法
  16. ZZULIOJ1076-1080Python解法
  17. 编写一个程序个人资料管理工具 考试题目 求大神帮忙 可以给一定报酬 万分感谢!
  18. 如何在PPT中同时插入多张图片且每张占一页
  19. 【掌上齐齐哈尔】市民网上换领驾驶证方便快捷
  20. postgresql10监控-使用EXTENSIONS模式

热门文章

  1. 本周大新闻|谷歌眼镜企业版正式停售;Meta重组大裁员
  2. 汽车之家精选论坛图片下载
  3. Edge浏览器兼容性设置,实用技巧,分享给你(2023新版)
  4. 想要用电脑玩游戏,好的显示器必不可少!电脑显示器要怎么选?
  5. sql怎么与oracle连接,sql怎么连接oracle数据库
  6. iOS 3级滚动地址
  7. Ruby gem的proxy代理设置方法
  8. 每天读论语《论语·学而》02
  9. ubuntu16.04运行PL-SVO
  10. 【机器学习基础】贝叶斯神经网络