Android使用辅助服务AccessibilityService实现自动化任务
Android 辅助服务(AccessibilityService)旨在帮助具有视觉、身体或年龄相关限制的用户更轻松地使用 Android 设备和应用。通过辅助服务,可以将一些人工操作自动化,从而解放用户的双手。
因此我们可以使用它来实现一些自动化任务,比如抢红包,测试,自动玩游戏(外挂?)。author: https://blog.csdn.net/keeng2008
- 编写辅助服务MyAccessibilityService,继承AccessibilityService
class MyAccessibilityService : AccessibilityService() {override fun onServiceConnected() {super.onServiceConnected()Log.i(TAG, "onServiceConnected")}override fun onAccessibilityEvent(event: AccessibilityEvent) {Log.i(TAG, "onAccessibilityEvent: $event")val packageName = event.packageName/* 处理界面变动事件 */}override fun onInterrupt() {Log.i(TAG, "onInterrupt")}
}
当辅助服务开启后,Service会开始运行,界面上的元素变动,窗口变动会回调onAccessibilityEvent。在其中可以实现模拟点击。
- 这个服务不能主动开启,需要用户在设置-无障碍中手动开启。
- 把MyAccessibilityService添加到Manifest
<serviceandroid:name=".accessbi.MyAccessibilityService"android:exported="true"android:label="控制辅助服务Demo"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService" /></intent-filter><meta-dataandroid:name="android.accessibilityservice"android:resource="@xml/my_accessibility" /></service>
在res/xml中添加文件 my_accessibility.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeAllMask"android:accessibilityFeedbackType="feedbackSpoken"android:accessibilityFlags="flagReportViewIds"android:canRetrieveWindowContent="true"android:canPerformGestures="true"android:notificationTimeout="100"/>
这样就已经注册好辅助服务,但是需要用户手动到“设置”中的“无障碍”,去启动无障碍功能。
- 引导用户直接跳转到无障碍中启动
- 3.1 判断当前是否已经启动
fun isAccessibilitySettingsOn(context: Context): Boolean {val accessibilityEnabled = Settings.Secure.getInt(context.contentResolver,Settings.Secure.ACCESSIBILITY_ENABLED)if (accessibilityEnabled != 1) return falseval value = Settings.Secure.getString(context.contentResolver,Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES) ?: return falsereturn value.contains(context.packageName) &&value.contains(MyAccessibilityService::class.java.simpleName)}
- 3.2 跳转到无障碍设置界面
发现未开启服务后,引导用户跳转到设置界面,手动打开。
fun openAccessibilitySetting(context: Context) {val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)context.startActivity(intent)}
- 3.3 开启后能否保持状态
经测试,如果进程被主动杀死重启,那么开关就被关闭了。
其它情况下即使关机重启,更新APP,它的状态能保持-
- AccessibilityService常用方法
- 获取当前的APP: val packageName = event.packageName
- 获取当前的Activity:
fun getActivityName(context: Context, event: AccessibilityEvent): String {val componentName = ComponentName(event.packageName.toString(), event.className.toString())try {var activityName = context.packageManager.getActivityInfo(componentName, 0).toString()activityName =activityName.substring(activityName.indexOf(" "), activityName.indexOf("}"))return activityName} catch (e: Exception) {}return ""}
不是每个event都能获取到Activity的,比如一些Toast,Dialog的事件,拿不到Activity; 所以可以把最后的Activity保存起来,随时读取。
- 通过文本获取当前界面的View
fun findViewByText(svr: AccessibilityAble, text: String): AccessibilityNodeInfo? {val nodes = svr.getRootNode()?.findAccessibilityNodeInfosByText(text)if (nodes != null) {for (node in nodes) {if (node.text == text) {return node}}}return nodes?.firstOrNull()
}
AccessibilityAble: 主是要封装了对 getService().rootInActiveWindow 的引用, 这样可以从当前的全局根结点开始寻找。
- 通过viewId获取当前界面的View
格式示例 :“APP包名:id/operator_normal_iv”
fun findViewById(svr: AccessibilityAble, viewId: String): AccessibilityNodeInfo? {val nodes = svr.getRootNode()?.findAccessibilityNodeInfosByViewId(viewId)return nodes?.firstOrNull()
}
- 模拟View点击
val btn: AccessibilityNodeInfo? = AccessibilityUtils.findViewByText(svr, "下次再说")
if (btn != null && btn.isClickable && btn.isVisibleToUser) {btn.performAction(AccessibilityNodeInfo.ACTION_CLICK)
}
- 通过手势长按指定坐标
fun performLongPress(svr: AccessibilityAble, point: PointF, durationMill: Long) {// 创建手势描述val gestureBuilder = GestureDescription.Builder()// 移动到指定坐标val path = Path().apply {moveTo(point.x, point.y)}val duration: Long = durationMill // 持续时间 毫秒val strokeDescription = GestureDescription.StrokeDescription(path, 0, duration)// 添加手势到描述gestureBuilder.addStroke(strokeDescription)val gesture = gestureBuilder.build()// 执行手势val cb = object : AccessibilityService.GestureResultCallback() {override fun onCompleted(gestureDescription: GestureDescription?) {Log.i(TAG, "onCompleted, $gestureDescription")}override fun onCancelled(gestureDescription: GestureDescription?) {Log.i(TAG, "onCancelled, $gestureDescription")}}val res = svr.getService().dispatchGesture(gesture, cb, null)Log.i(TAG, "dispatchGesture, res: $res")
}
- 点击Node所在位置:主要是有些文本不可点击,直接模拟点击该位置
fun performClick(svr: AccessibilityAble, node: AccessibilityNodeInfo) {val rect = Rect()node.getBoundsInScreen(rect)val centerP = PointF(rect.exactCenterX(), rect.exactCenterY())Log.i(TAG, "Start Simple Click at $centerP")performLongPress(svr,centerP,100L)
}
author: https://blog.csdn.net/keeng2008 有了这神器,能实现些什么新奇玩法呢?抢红包,自动打卡,继续探索中。
相关文章:
Android使用辅助服务AccessibilityService实现自动化任务
Android 辅助服务(AccessibilityService)旨在帮助具有视觉、身体或年龄相关限制的用户更轻松地使用 Android 设备和应用。通过辅助服务,可以将一些人工操作自动化,从而解放用户的双手。 因此我们可以使用它来实现一些自动化任务&a…...

工业大数据分析算法实战-day15
文章目录 day15特定数据类型的算法工业分析中的数据预处理工况划分数据缺失时间数据不连续强噪声大惯性系统趋势项消除 day15 今天是第15天,昨日是针对最优化算法、规则推理算法、系统辨识算法进行了阐述,今日主要是针对其他算法中的特定数据类型的算法…...
C语言实现顺序表详解
文章目录 [TOC] 1.前言🙋🏼♂️2.顺序表🧣2.1 顺序表概念🧣2.2 顺序表特点🧣2.2 顺序表作用🧣 3.顺序表基操🧤3.1 结构体初始化🎉3.2 顺序表初始化🎉3.3 顺序表创建&am…...
【ES6复习笔记】对象方法扩展(17)
对象方法扩展 在 JavaScript 中,对象是属性和方法的集合。除了内置的方法,我们还可以通过扩展对象的原型来添加新的方法。本教程将介绍如何使用 Object.is、Object.assign 和 Object.setPrototypeOf 方法来扩展对象。 1. Object.is 判断两个值是否完全…...

【视觉惯性SLAM:相机成像模型】
相机成像模型介绍 相机成像模型是计算机视觉和图像处理中的核心内容,它描述了真实三维世界如何通过相机映射到二维图像平面。相机成像模型通常包括针孔相机的基本成像原理、数学模型,以及在实际应用中如何处理相机的各种畸变现象。 一、针孔相机成像原…...
学习笔记(C#基础书籍)-- C#基础篇
(12.24) C#介绍:《第一章》 特点:语法简洁,面向对象,支持绝大部分的web标准,强大的安全机制(垃圾回收器),兼容性好(遵循.NET的公共语言规范【CL…...

操作系统(26)数据一致性控制
前言 操作系统数据一致性控制是确保在计算机系统中,数据在不同的操作和处理过程中始终保持正确和完整的一种机制。 一、数据一致性的重要性 在当今数字化的时代,操作系统作为计算机系统的核心,负责管理和协调各种资源,以确保计算机…...
ubuntu24.04使用opencv4
ubuntu24.04LTS自带opencv4.5代码实例 //opencv_example.cpp #include <opencv2/opencv.hpp> #include <iostream>int main() {// 读取图像cv::Mat img cv::imread("image.jpg", cv::IMREAD_COLOR);if (img.empty()) {std::cerr << "无法读…...

【项目构建】Gradle入门
本文适用: 不知道什么是项目构建,可以了解下Ant,Maven,Gradle的区别。知道什么是项目构建,了解Ant,Maven,可以看到Gradle是怎么做的。知道什么是项目构建,了解Ant,Maven&…...
Electron -- Electron应用主要核心(二)
Electron 应用主要由以下几个核心组成部分构成: 主进程(Main Process): Electron 应用的入口点是主进程,通常是 main.js 文件。它负责管理应用的生命周期,包括创建窗口、处理系统事件和应用更新等。主进程可…...

【前端开发】HTML+CSS+JavaScript前端三剑客的基础知识体系了解
前言 🌟🌟本期讲解关于HTMLCSSJavaScript的基础知识,小编带领大家简单过一遍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 …...

git命令恢复/还原某个文件、删除远程仓库中的文件
有时刚创建的远程仓库,可能无意中把一些没用的文件上传到仓库,本文介绍一下怎么删除这些文件。 一、git命令恢复某个文件 第一步:拉取最新代码 git pull 第二步: 查看git 修改的文件状态 git status 第三步:查看…...

二十一、Ingress 进阶实践
架构参考 使用hostnetwork,推荐的方式,使用单独的物理服务器,不部署业务pod的主机。 一、Ingress Nginx Controller 安装 采用helm的安装方式,进行部署。 官网地址: https://kubernetes.github.io/ingress-nginx/deploy/ github地址: https://github.com/kubernetes/in…...
ES学习Promise对象(九)
这里写目录标题 一、概念二、示例基本使用使用 Promise 对象封装Ajaxthen() 方法catch() 方法 一、概念 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。Promise 是一个对象,Promise 提供统一…...

寻找适合小户型的开源知识库open source knowledge base之路
寻找一个开源的知识库,为了把以前花很多时间收集的信息或是项目/课程资料放到一个容易归类和管理的私有自主系统中,以便更容易查阅,花更少时间收集、对比版本及分享等一系列管理工作,同时确保在需要时可以相对快速找到有用的资料&…...

Linux高级--2.6 网络面试问题
tcp 与 udp的区别 1.tcp 是基于连接的 UDP是基于数据包 2.处理并发的方式不通 a.tcp用epoll进行监听的 b. udp是模拟tcp的连接过程,服务端开放一个IP端口,收到连接后,服务端用另一个IP和端口发包给客户端。 3.tcp根据协议MTU黏包及…...
在 CentOS 7 上安装 Node.js 20 并升级 GCC、make 和 glibc
在 CentOS 7 上安装 Node.js 20 并升级 GCC、make 和 glibc 📖 前言 在 CentOS 7 上使用 NVM 安装 Node.js 后,可能会遇到如下问题: node: /lib64/libm.so.6: version GLIBC_2.27’ not found (required by node) node: /lib64/libc.so.6:…...

音视频入门基础:MPEG2-TS专题(20)——ES流简介
《T-REC-H.222.0-202106-S!!PDF-E.pdf》第27页对ES进行了定义。ES流是PES packets(PES包)中编码的视频、编码的音频或其他编码的比特流。一个ES流(elementary stream)在具有且只有一个stream_id的PES packets序列中携带࿱…...

五子棋小游戏设计(Matlab)
基于Matlab的五子棋小游戏设计 (完整源码运行呈现的GUI界面) (完整的设计说明报告) 需要请随时联系博主,博主基本都在线,能秒回! 随着计算机技术的发展,将传统棋类游戏与编程技术…...
基于Pycharm与数据库的新闻管理系统(3)MongoDB
pip3 install pymongo 1.连接到MongoDB数据库 文件地址:db/mongo_db.py 从 pymongo 模块中导入 MongoClient 类;创建 MongoClient 的一个实例,该实例尝试使用提供的MongoDB连接字符串连接到MongoDB服务器。 from pymongo import MongoClie…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...

GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...

【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验
2024年初,人工智能编程工具领域发生了一次静默的变革。当字节跳动宣布退出其TRAE项目(一款融合大型语言模型能力的云端AI编程IDE)时,技术社区曾短暂叹息。然而这一退场并非终点——通过开源社区的接力,TRAE在WayToAGI等…...
k8s从入门到放弃之Pod的容器探针检测
k8s从入门到放弃之Pod的容器探针检测 在Kubernetes(简称K8s)中,容器探测是指kubelet对容器执行定期诊断的过程,以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...