300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > android 红包功能 Android 微信抢红包实现

android 红包功能 Android 微信抢红包实现

时间:2023-04-12 23:07:28

相关推荐

android 红包功能 Android 微信抢红包实现

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

)

}

}

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。