注册

android 微信抢红包工具 AccessibilityService(下)

接:android 微信抢红包工具 AccessibilityService(上)

四、完整代码

MyNotificationListenerService

class MyNotificationListenerService : NotificationListenerService() {

   override fun onNotificationPosted(sbnStatusBarNotification?) {
       super.onNotificationPosted(sbn)

       val extras = sbn?.notification?.extras
       // 获取接收消息APP的包名
       val notificationPkg = sbn?.packageName
       // 获取接收消息的抬头
       val notificationTitle = extras?.getString(Notification.EXTRA_TITLE)
       // 获取接收消息的内容
       val notificationText = extras?.getString(Notification.EXTRA_TEXT)
       if (notificationPkg != null) {
           Log.d("收到的消息内容包名:"notificationPkg)
           if (notificationPkg == "com.tencent.mm"){
               if (notificationText?.contains("[微信红包]"== true){
                   //收到微信红包了
                   val intent = sbn.notification.contentIntent
                   intent.send()
              }
          }
      } Log.d("收到的消息内容""Notification posted $notificationTitle & $notificationText")
  }

   override fun onNotificationRemoved(sbnStatusBarNotification?) {
       super.onNotificationRemoved(sbn)
  }
}

MyAccessibilityService

class MyAccessibilityService : AccessibilityService() {

   override fun onAccessibilityEvent(eventAccessibilityEvent) {
       val eventType = event.eventType
       when (eventType) {
           AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED -> handleNotification(event)
           AccessibilityEvent.TYPE_WINDOW_STATE_CHANGEDAccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED -> {
               val className = event.className.toString()
               Log.e("测试无障碍",className)
               when (className) {
                   "com.tencent.mm.ui.LauncherUI" -> {
                       // 我管这叫红包卡片页面
                       getPacket()
                  }
                   "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI" -> {
                       // 貌似是老UI debug没发现进来
                       openPacket()
                  }
                   "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyNotHookReceiveUI" -> {
                       // 应该是红包弹框UI新页面 debug进来了
                       openPacket()
                  }
                   "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI" -> {
                       // 红包详情页面 执行关闭操作
                       close()
                  }
                   "androidx.recyclerview.widget.RecyclerView" -> {
                       // 这个比较频繁 主要是在聊天页面 有红包来的时候 会触发 当然其他有列表的页面也可能触发 没想到好的过滤方式
                       getPacket()
                  }
              }
          }
      }
  }

   /**
    * 处理通知栏信息
    *
    * 如果是微信红包的提示信息,则模拟点击
    *
    * @param event
    */
   private fun handleNotification(eventAccessibilityEvent) {
       val texts = event.text
       if (!texts.isEmpty()) {
           for (text in texts) {
               val content = text.toString()
               //如果微信红包的提示信息,则模拟点击进入相应的聊天窗口
               if (content.contains("[微信红包]")) {
                   if (event.parcelableData != null && event.parcelableData is Notification) {
                       val notificationNotification? = event.parcelableData as Notification?
                       val pendingIntentPendingIntent = notification!!.contentIntent
                       try {
                           pendingIntent.send()
                      } catch (eCanceledException) {
                           e.printStackTrace()
                      }
                  }
              }
          }
      }

  }

   /**
    * 关闭红包详情界面,实现自动返回聊天窗口
    */
   @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
   private fun close() {
       val nodeInfo = rootInActiveWindow
       if (nodeInfo != null) {
           val list = nodeInfo.findAccessibilityNodeInfosByText ("的红包")
           if (list.isNotEmpty()) {
               val parent = list[0].parent.parent.parent
               if (parent != null) {
                   for ( j in 0 until  parent.childCount) {
                       val child = parent.getChild (j)
                       if (child != null && child.isClickable) {
                           child.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                      }
                  }

              }

          }
      }
  }

   /**
    * 模拟点击,拆开红包
    */
   @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
   private fun openPacket() {
       Log.e("测试无障碍","点击红包")
       Thread.sleep(100)
       val nodeInfo = rootInActiveWindow
       if (nodeInfo != null) {
           val list = nodeInfo.findAccessibilityNodeInfosByText ("的红包")
           for ( i in 0 until list.size) {
               val parent = list[i].parent
               if (parent != null) {
                   for ( j in 0 until  parent.childCount) {
                       val child = parent.getChild (j)
                       if (child != null && child.isClickable) {
                           Log.e("测试无障碍","点击红包成功")
                           child.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                      }
              }

          }

          }
      }

  }

   /**
    * 模拟点击,打开抢红包界面
    */
   @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
   private fun getPacket() {
       Log.e("测试无障碍","获取红包")
       val rootNode = rootInActiveWindow
       val caches:ArrayList<Any> = ArrayList()
       recycle(rootNode,caches)
       if(caches.isNotEmpty()){
           for(index in 0 until caches.size){
               if(caches[indexis AccessibilityNodeInfo && (index == 0 || caches[index-1!is String )){
                   val node = caches[indexas AccessibilityNodeInfo
//                   node.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                   var parent = node.parent
                   while (parent != null) {
                       if (parent.isClickable) {
                           parent.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                           Log.e("测试无障碍","获取红包成功")
                           break
                      }
                       parent = parent.parent
                  }
                   break
              }
          }
      }

  }

   /**
    * 递归查找当前聊天窗口中的红包信息
    *
    * 聊天窗口中的红包都存在"微信红包"一词,因此可根据该词查找红包
    *
    * @param node
    */
   private fun recycle(nodeAccessibilityNodeInfo,caches:ArrayList<Any>) {
       if (node.childCount == 0) {
           if (node.text != null) {
               if ("已过期" == node.text.toString() || "已被领完" == node.text.toString() || "已领取" == node.text.toString()) {
                   caches.add("#")
              }

               if ("微信红包" == node.text.toString()) {
                   caches.add(node)
              }
          }
      } else {
           for (i in 0 until node.childCount) {
               if (node.getChild(i!= null) {
                   recycle(node.getChild(i),caches)
              }
          }
      }
  }

   override fun onInterrupt() {}
   override fun onServiceConnected() {
       super.onServiceConnected()
       Log.e("测试无障碍id","启动")
       val infoAccessibilityServiceInfo = serviceInfo
       info.packageNames = arrayOf("com.tencent.mm")
       serviceInfo = info
  }
}

5、总结

此文是对AccessibilityService的使用的一个梳理,这个功能其实不麻烦,主要是一些细节问题,像自动领取支付宝红包,自动领取QQ红包或者其他功能等也都可以用类似方法实现。目前实现了微信和钉钉的,剩下的支付宝QQ啥的没啥人用,就不想做了,不过原理都是一样的,

源码地址: gitee.com/wlr123/acce…

使用时记得开启下对应权限,设置下后台运行权限,电量设置里面允许后台运行等,以及通知栏权限,以保证稳定运行


作者:我有一头小毛驴你有吗
来源:juejin.cn/post/7196949524061339703

0 个评论

要回复文章请先登录注册