pen abstract class EventHandler(val service: AccessibilityService) {

//任务队列,重复事件较多,按顺序处理并发事件,找到目标node后清空队列

var eventQueue = LinkedList()

/**

* 将event加到队尾

* 队列中有正在处理的任务则等待处理完成

* 没有则开启一个新的任务

* */

fun pushEvent(event: AccessibilityEvent) {

if (eventQueue.size == 0) {

eventQueue.add(event)

while (eventQueue.size > 0) {

//找到目标node,直接终止任务,清空当前队列,找不到则继续下一个event

if (handleEvent(eventQueue.first)) {

eventQueue.clear()

break

} else {

eventQueue.removeFirst()

}

}

} else {

eventQueue.add(event)

}

}

abstract fun handleEvent(event: AccessibilityEvent): Boolean

}

--------------------------------父子分割线-------------------------------------

class WeChatEventHandler(service: AccessibilityService) : EventHandler(service) {

val TAG = "WeChatEventHandlerLog"

/**

* @return 在一个任务队列中是否找到了目标node,true为找到

* */

override fun handleEvent(event: AccessibilityEvent): Boolean {

Log.i(TAG, event.eventType.toString())

when (event.eventType) {

//效果不好,已废弃,改为使用 NotificationListenerService

// AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED -> {

// checkNotification(it)

// }

//根据调试后,确定微信在出现红包是会多次受到这个event,排队处理event,找到关键词并点击即可

AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED -> {

findNodeByText("微信红包")?.let {

clickNode(it)

return true

}

}

//微信红包弹出来以后,只收到这一个event,但界面加载又需要时间,所以这里间隔100ms,重试10次找到开红包的按钮,找到则终止

AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED -> {

//找到开红包按钮,重试10次

GlobalScope.launch {

var retryTimes = 0

while (retryTimes < 10) {

delay(100)

val node = findNodeByDes("开")

if (node != null) {

clickNode(node)

break

} else {

retryTimes++

}

}

}

return false

}

else -> {

}

}

return false

}

private fun findNodeByText(matchStr: String): AccessibilityNodeInfo? {

return findNode(matchStr) {

it.text?.toString() ?: ""

}

}

private fun findNodeByDes(matchStr: String): AccessibilityNodeInfo? {

return findNode(matchStr) {

it.contentDescription?.toString() ?: ""

}

}

/**

* 用Stack 模拟递归,避免栈溢出

* 递归遍历屏幕上的所有节点,通过文案来匹配需要找到的目标

* */

private fun findNode(

matchStr: String,

matchRule: (AccessibilityNodeInfo) -> String

): AccessibilityNodeInfo? {

try {

val nodeGroupStack = Stack()

var node = service.rootInActiveWindow

while (true) {

val nodeList = mutableListOf()

if (node.childCount > 0) {

for (i in 0 until node.childCount) {

val child = node.getChild(i)

if (child.childCount > 0) {

nodeGroupStack.push(child)

} else {

val text = child.text?.toString() ?: ""

//确认是没用的红包,就可以放弃这个模块了

if (text.contains("已领取") || text.contains("已被领完")) {

break

}

nodeList.add(child)

}

}

} else {

val text = node.text?.toString() ?: ""

//在列表中发现没用的红包,跳出循环,继续找下一个红包

if (text.contains("已领取") || text.contains("已被领完")) {

continue

}

nodeList.add(node)

}

nodeList.forEach { child ->

var content = matchRule(child)

//各种没抢到红包的情况,直接返回或者回主页,不要遮挡屏幕,以免收不到后续红包

val text = child.text?.toString() ?: ""

if (text.contains("已存入零钱") || text.contains("个红包,") || text.contains("个红包共") || text.contains("手慢了,")) {

if (AppConfig.mode == 0) {

service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK)

} else {

service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK)

service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME)

}

service.rootInActiveWindow

}

if (content == matchStr) {

return child

}

}

//用循环模拟递归,避免栈溢出

if (nodeGroupStack.size > 0) {

node = nodeGroupStack.pop()

} else {

break

}

}

} catch (e: Exception) {

Log.e(TAG, e.message.toString())

}

return null

}

/**

* 点击节点

* 有click事件则调用click

* 没有就获取坐标,模拟点击

* */

private fun clickNode(node: AccessibilityNodeInfo) {

if (node.isClickable) {

Log.i(TAG, "clickBtn: ${node.text}")

node.performAction(AccessibilityNodeInfo.ACTION_CLICK)

} else {

//点击屏幕坐标

Rect().let { rect ->

node.getBoundsInScreen(rect)

val x = (rect.left + rect.right) / 2

val y = (rect.top + rect.bottom) / 2

dispatchGestureClick(x, y)

Log.i(TAG, "clickScreen: ${node.text} , x: $x , y: $y")

}

}

}

/**

* 点击指定位置

* api > 24

*/

private fun dispatchGestureClick(x: Int, y: Int) {

val path = Path()

path.moveTo(x.toFloat(), y.toFloat())

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

service.dispatchGesture(

GestureDescription.Builder().addStroke(

GestureDescription.StrokeDescription(

path,

0,

200

)

).build(),

null,

null

)

}

}

}

android 红包功能,Android 微信抢红包实现相关推荐

  1. android红包功能程序,微信小程序实现发红包功能

    本文实例为大家分享了微信小程序实现发红包的具体代码,供大家参考,具体内容如下 目前此功能尚在内测,无法申请.此博文仅示例. 流程效果图: 图片1触发wx.sendBizRedPacket({})吊起图 ...

  2. android远程打电话,Android打电话功能 Android实战教程第三篇之简单实现拨打电话功能...

    想了解Android实战教程第三篇之简单实现拨打电话功能的相关内容吗,杨道龙在本文为您仔细讲解Android打电话功能的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Android拨打电话 ...

  3. android 红包功能,[原创]实现某app的抢红包功能

    目录 内容摘要写这个插件的原因是因为经常使用这个app,而且每天早上这个app都会发红包,然而每次都抢不到,很懊恼,而最近也一直跟着 r0ysue 大佬在学习安卓逆向相关的知识,就突发奇想,所以就拿来 ...

  4. android黑科技系列——微信抢红包插件原理解析和开发实现

    一.前言 自从几年前微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...

  5. Android 分享功能之 微信 图片分享

    前言:如果 有关 QQ好友 纯文本分享的问题 ,可点查看 Android 分享功能实现与 QQ 纯文本分享. 我们都知道,通过 微信官方 分享sdk 支持图片分享,而且有多种方式.官方链接 可直接查看 ...

  6. php写抢红包,红包生成函数(微信抢红包)

    最近自己开发了一个类似微信抢红包的功能,在网上找了很多红包生成的函数,但都不是那么完美,于是自己动手写了一个. ( 阿荣原创^_^ ) //$money 是发红包的总金额, $num 红包生成的数量 ...

  7. android倒计时功能,android实现倒计时功能(开始、暂停、0秒结束)

    本文实例为大家分享了android实现倒计时功能的具体代码,供大家参考,具体内容如下 [思路]:通过 timer 执行周期延时的任务,handler 中将计时信息更新,并在计时结束时结束 timer ...

  8. android倒计时功能,Android 实现列表倒计时功能

    Android 实现列表倒计时功能 发布时间:2020-08-21 21:47:11 来源:脚本之家 阅读:147 作者:Choi晨 单个计时器,然后遍历数据 刷新条目: 两种实现方式:1.Handl ...

  9. 用python语言模拟微信红包_python 模拟微信抢红包 基础语法实现demo

    1.实现微信抢红包 简易demo版 : 代码如下: from decimalimport Decimal # 提供了随机方法 import random print('$$$$$$weichat模拟微 ...

最新文章

  1. 程序员抱怨老婆追王一博入魔,长期被冷落想离婚
  2. smarty中的内建函数(二)if、section
  3. 数据中心母线布置方式
  4. NioEventLoop 的实例化过程
  5. vue调用顺序(初学版) index.html → main.js → app.vue → index.js → components/组件 测试
  6. centos安装python3.7详细过程 2020
  7. Android 系统(188)---In-Cell、On-Cell、OGS三种屏幕技术
  8. IOS的四种数据存储方式及优劣
  9. Spring Boot 集成undertow作为web容器分析
  10. NFR24C0L中文使用手册、stm32硬件SPI与模拟SPI比较:
  11. gitlab太占内存怎么办?一招帮你解决这个问题
  12. 幼儿园的计算机一年级的教案,我上一年级了幼儿园教案
  13. 2023初级会计详细学习计划打卡表!自律逆袭,一次上岸!
  14. CCF大会腾源会专场即将召开,聚焦基础软件与开发语言未来发展
  15. java中bio_java中bio是什么
  16. 【C++】C++数组初始化方法
  17. java进阶----集合
  18. JTR(John The Ripper)的ssh密钥破解记录
  19. ae教程 (五)滤镜特效 (四)音频特效
  20. [渝粤教育] Northwest AF University Crop Cultivation Science 参考 资料

热门文章

  1. Android平台使用-谷歌广告联盟AdMob-赚取收益的编程方法
  2. 一站式、整套智能家居解决方案——HomeKit?绿米?华为还是智汀?
  3. 膨胀珍珠岩保温材料英国UKCA认证—EN 14316-1
  4. MySQL驱动到什么东西?
  5. CAD随机孔隙3D插件 孔隙结构 多孔结构模型
  6. Spring源码解析十五
  7. 内衣市场新变局,都市丽人的“不破不立”
  8. 聊聊并发编程的12种业务场景
  9. Jmeter入门教程之配置原件(二)
  10. python基础十 函数(下)匿名函数、高阶函数、闭包、装饰器