python 安卓模拟点击_Android后台模拟点击探索(附源码)

2023-11-17

工作中我们需要自制一套工具,其中遇到需要模拟点击事件的需求,类似按键精灵的功能,支持后台持续运行,满足触发条件时完成点击。

经过一番探索,一共整理出两种不同的方案:AccessibilityService 和 adb shell命令,读者可自行选择合适的场景。

AccessibilityService

无障碍模式是我首先想到的方案,对于不知道Android无障碍模式的,可自行百度。这里简单说明一下,AccessibilityService是Android为残障人士提供的贴心功能,比如可以报出当前页面有哪些按钮balabala。使用官方提供的一些列API,我们还可以完成一些自动运行的“黑科技”操作,比如早些年的红包插件、微信自动回复插件、自动点赞插件等。

本方案原理比较简单:扫描当前页面的View树,找到目标控件,模拟点击操作,下面详细阐述。

添加配置文件

首先需要在res目录下建立配置文件:accessible_service_config.xml ,名字随意取。

<?xml version="1.0" encoding="utf-8"?>

xmlns:android="http://schemas.android.com/apk/res/android"

android:accessibilityEventTypes="typeAllMask"

android:accessibilityFeedbackType="feedbackGeneric"

android:accessibilityFlags="flagReportViewIds"

android:canRetrieveWindowContent="true"

android:notificationTimeout="100"

android:description="@string/description"

android:packageNames="目标包名"/>

accessibilityEventTypes:设置响应事件的类型,这里设置typeAllMask,就是响应全部类型的事件。

accessibilityFeedbackType:设置回馈给用户的方式,有语音播出和振动,这里使用通用类型。

notificationTimeout:设置响应时间。

packageNames:目标包名,比如红包插件就要设置微信包名,关于包名如何获取,下文会提到。

继承AccessibilityService编码

接着我们继承AccessibilityService新建AutoClickAccessibilityService,重写onAccessibilityEvent(AccessibilityEvent event)。

public class AutoClickAccessibilityService extends AccessibilityService {

private static final String TAG = "GK";

@Override

public void onAccessibilityEvent(AccessibilityEvent event) {

ztLog("===start===");

try {

//拿到根节点

AccessibilityNodeInfo rootInfo = getRootInActiveWindow();

if (rootInfo == null) {

return;

//开始遍历,这里拎出来细讲,直接往下看正文

if (rootInfo.getChildCount() != 0) {

……

}

} catch (Exception e) {

ztLog("Exception:" + e.getMessage(), true);

}

}

拿到根节点以后,我们有两种方式开始寻找目标节点:

根据View id:findAccessibilityNodeInfosByViewId

根据控件文案:findAccessibilityNodeInfosByText

这里我们拿魅族手机自带的音乐App做例子,假如我们需要自动点击下图的 专栏 :

2018124120251324.jpg?201802412315

使用findAccessibilityNodeInfosByViewId寻找目标

我们可以使用findAccessibilityNodeInfosByViewId(),通过id找到目标节点,关于View id,可以使用DDMS中的Dump View Hierarchy for UI Automator,就是点击下图按钮(不知道如何打开eclipse或者AS的DDMS的同学可以自行百度):

2018124120457271.png?201802412511

稍等片刻,生成屏幕快照,并解析出View树,从右下的属性框就可以找到id,同时仔细看,包名也可以获取到啦~

2018124120519786.jpg?201802412615

这里很有可能因为目标apk混淆严重而读不到id,比如是个?,那么可以尝试第二个方法。

使用findAccessibilityNodeInfosByText寻找目标

使用findAccessibilityNodeInfosByText("最热MV"),顾名思义,就是根据文案找控件。

找到控件以后,就可以执行点击操作了,但是且慢,这里有个坑。

因为注意看这里的view树:

2018124120628139.png?201802412645

无论我们根据id还是文案,找到的可能只是一个TextView或者Button,但是根据我们日常经验,我们肯定是给其父布局设置的点击事件,也就是这里的LinearLayout或者FrameLayout。

所以我的方案是根据View树的结构,自行遍历。比如这里的View树结构如下:

2018124120654699.png?20180241275

我先做深度优先遍历找到GridView,然后遍历它所有孩子直至找到专栏这个TextView,为什么我不直接DFS找到专栏呢?因为我要记录它的父节点甚至爷爷节点,方便接下来执行点击操作。

如果有同学使用这种方案,建议根据实际View树的结构,自行遍历寻找,我的代码如下:

/**

* 深度优先遍历寻找目标节点

*/

private void DFS(AccessibilityNodeInfo rootInfo) {

if (rootInfo == null || TextUtils.isEmpty(rootInfo.getClassName())) {

return;

}

if (!"android.widget.GridView".equals(rootInfo.getClassName())) {

ztLog(rootInfo.getClassName().toString());

for (int i = 0; i < rootInfo.getChildCount(); i++) {

DFS(rootInfo.getChild(i));

}

} else {

ztLog("==find gridView==");

final AccessibilityNodeInfo GridViewInfo = rootInfo;

for (int i = 0; i < GridViewInfo.getChildCount(); i++) {

final AccessibilityNodeInfo frameLayoutInfo = GridViewInfo.getChild(i);

//细心的同学会发现,我代码里的遍历的逻辑跟View树里显示的结构不一样,

//快照显示的FrameLayout下明明该是LinearLayout,我这里却是TextView,

//这个我也不知道,实际调试出来的就是这样……所以大家实操过程中也要注意了

final AccessibilityNodeInfo childInfo = frameLayoutInfo.getChild(0);

String text = childInfo.getText().toString();

if (text.equals("专栏")) {

performClick(frameLayoutInfo);

} else {

ztLog(text);

}

}

}

}

private void performClick(AccessibilityNodeInfo targetInfo) {

targetInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);

}

AndroidManifest文件添加Service配置

AccessibilityService也是一个Servcie,所以要在AndroidManifest配置一下。

android:name=".AutoClickService"

android:exported="false"

android:label="自动点击Demo"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >

android:name="android.accessibilityservice"

android:resource="@xml/accessible_service_config" />

至此无障碍模式方案就讲完了,运行之后,需要在手机设置中的无障碍里打开对应的开关:

2018124120755067.png?20180241289

2018124120817289.png?201802412829

打开以后,自动点击功能可以自动后台运行了,不想用时可以在上图开关那里关闭即可。

以后需要先运行App,再打开开关,开启功能。

无障碍模式虽然用着挺舒服,但是在很多厂商的系统里,已经打开的无障碍模式隔一段时间经常会被自动关闭,比如MIUI系统里就要给App加开机运行的权限。

而厂商自带的无障碍就没事,猜测系统里内置了处理,这也是无障碍模式的一个坑吧。

小结

最后总结一下,AccessibilityService是一个很有趣的功能,发挥想象力可以做很多事,但是要小心踩坑:

通过findAccessibilityNodeInfosByViewId或者findAccessibilityNodeInfosByText找到的目标控件不一定是你想要的点击控件

各家厂商系统可能对无障碍模式内置了屏蔽处理

adb shell命令

adb可以方便我们直接高效的操作真机,比如安装apk,批量安装apk,复制文件等,而模拟点击事件也是可以通过adb命令完成的。

我是突然想到,前阵子看过网上流传的一个“微信跳一跳”的辅助,使用python + adb完成。

原理就是adb负责截图,python负责图像识别像素计算距离,最后再由adb模拟点击。

如果我们需要点击的目标,坐标相对确定,那我们直接在代码里执行adb命令模拟点击即可。

真机实验

我们先用USB连接真机,在cmd命令行工具里:

adb shell

shell@PRO6:/ $ input tap 125 521

shell@PRO6:/ $

这里的意思就是点击屏幕上 (x, y) = (125, 521)的地方。果然手机响应了,缺点就是响应时间略长,感觉有1秒左右。

同理其他手势操作也可以完成,这里不作详解,感兴趣的可以自行搜索。

下面我们需要做的就是在代码里完成上述操作,并且可以持续在后台运行。这里我也是踩坑无数,听我慢慢吐槽。

寻找后台执行adb命令的方案

ProcessBuilder — OUT

没什么好说的,直接看代码:

int x = 0, y = 0;

String[] order = { "input", "tap", " ", x + "", y + "" };

try {

new ProcessBuilder(order).start();

} catch (IOException e) {

Log.i("GK", e.getMessage());

e.printStackTrace();

}

这种版本,在Activity中可行,但是切后台不行……这肯定无法满足需求,再找!

Instrumentation — OUT

try {

Instrumentation inst = new Instrumentation();

inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0));

inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0));

Log.i("GK", "模拟点击" + x + ", " + y);

} catch (Exception e) {

Log.e("Exception when sendPointerSync", e.toString());

}

这种版本和上一个一模一样,不能后台,差评!!

救世主Runtime登场

private OutputStream os;

/**

* 执行ADB命令: input tap 125 340

*/

private final void exec(String cmd) {

try {

if (os == null) {

os = Runtime.getRuntime().exec("su").getOutputStream();

}

os.write(cmd.getBytes());

os.flush();

} catch (Exception e) {

e.printStackTrace();

Log.e("GK", e.getMessage());

}

}

后台问题迎刃而解!

添加合适的时机

目前我们把核心功能做完了,最后需要做的就是找到合适的时机,执行操作。

首先我们的容器肯定是一个Service,然后后台不断的判断当前app是否是目标app,如果是的话,再执行自动点击操作。

所以我们需要判断当前前台app的包名或者Activity的名字是否是我们的目标。

/**

* 如果前台APP是目标apk

*/

private boolean isCurrentAppIsTarget() {

String name = getForegroundAppPackageName();

if (!TextUtils.isEmpty(name) && PACKAGE_NAME.equalsIgnoreCase(name)) {

return true;

}

return false;

}

/**

* 获取前台程序包名

*/

public String getForegroundAppPackageName() {

ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

List lr = am.getRunningAppProcesses();

if (lr == null) {

return null;

}

for (RunningAppProcessInfo ra : lr) {

if (ra.importance == RunningAppProcessInfo.IMPORTANCE_VISIBLE || ra.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {

Log.i("GK", ra.processName);

return ra.processName;

}

}

return "";

}

以上就是adb shell方案,这种方案缺陷也比较明显,就是要求 自动点击的位置不能改变。

对于如何获取点击位置的坐标,可以打开开发者选项中的指针位置:

2018124120942630.png?201802412954

直接查看坐标。

总结

模拟点击这种需求,我们一般都不会用到,也有点歪门邪道的意思。但是无论什么需求,中间的探索过程才最珍贵。技术也是人,不是每次都会有说干就干的决心和勇气,保持一颗好奇心,珍惜每次探索的机会,学有所得,小有收获,也未尝不是一种自我认可。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 安卓模拟点击_Android后台模拟点击探索(附源码) 的相关文章

  • java开发sublime插件_开发者最常用的8款Sublime text 3插件

    5 SublimeCodeIntel Sublime Code Intel 作为一个代码提示和补全插件 支持Javascript Mason XBL XUL RHTML SCSS python HTML Ruby Python3 XML S
  • 【常见的编解码场景】

    常见的编解码场景 一 编码与解码 1 1 字符编解码 字符集和编码 编解码过程分析 编解码举例 1 2 http url编码 1 3 http body编码 1 4 压缩编码 1 5 对象编码 netty框架中的编码解码 dubbo框架的编
  • 微信小程序中主包和分包过大,详解分包问题

    哈喽 大家好呀 小韵携原创博文给大家请安啦 前言 开发微信小程序时 若项目比较大 必定要分包 当项目过于大时 则需要细致 谨慎地对项目进行分包优化和精简 这是一个不可避免地问题 网上的大多数分包优化都是针对于小项目的普通官方分包优化 并未将
  • 利用Java EE相关技术实现一个简单的购物车系统

    利用JSP编程技术实现一个简单的购物车程序 具体要求如下 1 用JSP编程实现一个登录页面 登录信息中有用户名和密码 分别用两个按钮来提交和重置登录信息 另外 登录页面请实现记住密码功能 2 编写一个JSP程序来获取用户提交的登录信息并查询
  • Redis Cluster集群主从切换踩坑记

    因为项目的原因采用了Redis Cluster 3主3从 每台主机1主1从 集群信息如下 10 135 255 72 20011 gt cluster nodes 7b662b36489a6240aa21d1cf7b04b84019254b
  • STL源码剖析之一:空间适配器(allocator)

    空间适配器是 所有组件的核心 每个操作系统都有自己的内存分配器 他承担着内存分配 管理 释放 作为模版参数传递到每个容器去 allocate函数分配一片连续的未被构造的空间备用 deallocate 函数释放空间 construct函数调用
  • nodejs 中 token 的使用

    前言 token 验证 在设计登录注册和一些权限接口时发挥作用 以nodejs为例 谈一谈jsonwebtoken的使用 正文 一 安装 npm i jsonwebtoken 二 使用 首先 需要提供一个密匙 也就是一个字符串 用于toke
  • FPGA零基础学习之Vivado-ROM使用教程

    FPGA零基础学习之Vivado ROM使用教程 本系列将带来FPGA的系统性学习 从最基本的数字电路基础开始 最详细操作步骤 最直白的言语描述 手把手的 傻瓜式 讲解 让电子 信息 通信类专业学生 初入职场小白及打算进阶提升的职业开发者都
  • 云原生之使用Docker部署Magma导航页

    云原生之使用Docker部署Magma导航页 一 Magma导航页介绍 1 1 Magma导航页简介 1 2Magma导航页特点 二 本地环境介绍 2 1 本地环境规划 2 2 本次实践介绍 三 本地环境检查 3 1 检查Docker服务状
  • 扛住阿里双十一高并发流量,Sentinel是怎么做到的?

    Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景 本文介绍阿里开源限流熔断方案 Sentinel 功能 原理 架构 快速入门以及相关框架比较 基本介绍 1 名词解释 服务限流 当系统资源不够 不足以应对大量请求 对系统
  • # winform实现一个服务端和多个客户端进行通信

    参看此链接 http www cnblogs com longwu archive 2011 08 25 2153636 html 在上述代码的基础上进行了修改 包括一些捕获异常以及按钮的应用 扩充了一个listbox确保服务端可以选择和不
  • linux echo输出转义换行回车引号

    echo 输出引号的正确格式 echo 123 echo 123 echo 输出回车换行 制表符的正确格式 echo e n123 echo e n123 echo e t123 echo e t123 输出结果
  • springboot使用pagehelper进行分页

    上次的博客项目 使用到了分页 这里总结一下 1 项目环境 IDE IDEA 语言 java 框架 springboot 模板引擎 thymeleaf 2 效果 3 pom xml
  • 贪吃蛇视频教程

    http gameinstitute qq com lore catalog 10017
  • nvm切换node版本

    nvm是一个node的版本管理工具 可以简单操作node版本的切换 安装 查看等等 与npm不同的是 npm是依赖包的管理工具 nvm 主要为了解决 node js 各种版本存在不兼容现象 1 下载 可去github上下载相关版本 链接地址
  • cmd命令解密Bitlocker

    解锁 manage bde unlock C Recovery 加锁 manage bde lock C 解密 manage bde off C 加密 manage bde on C C表示解锁的盘符 解密需要一定时间 可以用manage
  • 利用python拼接图片代码_Python实现图片拼接的代码

    具体代码如下所示 import os from PIL import Image UNIT SIZE 220 the size of image save path root group dia zxb Code lip CycleGAN
  • python PriorityQueue遍历

    要写一段遍历PriorityQueue中每个元素的代码 去网上找到的都是for循环 get 但是这样会把PriorityQueue中的元素取出来 得 问了chatGPT 没想到真有用 from queue import PriorityQu
  • Oracle 中 decode 函数用法

    Oracle 中 decode 函数用法 含义解释 decode 条件 值1 返回值1 值2 返回值2 值n 返回值n 缺省值 该函数的含义如下 IF 条件 值1 THEN RETURN 翻译值1 ELSIF 条件 值2 THEN RETU

随机推荐

  • 最新QQ强制搜索Api接口

    强制搜索QQ接口 QQ隐藏搜索不到的把他QQ放在 后面然后直接搜索链接就可以搜索到了 QQ设置了隐藏无法搜索使用这个隐藏都不管用的 进入官网 https apis hackeus cn 找到强制搜索接口点进去 后面输入QQ号即可
  • 用户账户控制(无法截图/退出全屏/使用窗口模式)

    用户账户控制提示框无法截图 这是我遇到的问题 如下 就是这种对话框 一般是程序请求管理员权限运行 就会弹出 默认是全屏状态 无法截图 试过什么PrintScreen等均不行 这里提供一个办法 把该提示框改变为窗口模式 而非全屏 就可以使用截
  • 数据结构--二叉堆与优先队列

    堆的一些性质 1 堆是一颗完全二叉树 2 堆的顶端一定是 最大 最小 的 但是要注意一个点 这里的大和小并不是传统意义下的大和小 它是相对于优先级而言的 3 堆一般有两种样子 小根堆和大根堆 分别对应第二个性质中的 堆顶最大 堆顶最小 对于
  • 毕业设计 - 基于云平台的火灾报警器 - stm32 物联网 单片机 OneNET云平台

    文章目录 0 简介 1 项目简介 2 开发环境 3 火焰传感器 4 连接OneNET云平台 5 演示效果 6 最后 0 简介 Hi 大家好 学长今天向大家介绍一个 单片机项目 基于云平台的火灾报警器 stm32 物联网 单片机 OneNET
  • 【linux kernel】挂载根文件系统之rootfs

    挂载根文件系统之rootfs 文章目录 挂载根文件系统之rootfs 一 开篇 二 rootfs根文件系统 2 1 初始化rootfs 2 2 挂载rootfs文件系统 2 3 创建简单的rootfs根文件系统目录和文件 2 4 打开0 1
  • [Python系列-27]:命令行解析器argparse详解

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 122276305 目录 第1章 arg
  • GB/T28181-2022相对2016版“基于TCP协议的视音频媒体传输要求“规范解读和技术实现

    规范解读 GB T28181 2022和GB T28181 2016规范 有这么一条 更改了附录 D 基于 TCP 协议的视音频媒体传输要求 见附录 D 2016 年版的附录 L 本文主要是针对GB T28181 2022里面提到的 基于
  • 【Java】Excel中添加下拉框

    0 两种方式 有两种方式可以实现 我仅在此记录一下 POI Hutool 1 使用 POI import org apache poi ss usermodel DataValidation import org apache poi ss
  • Web自动化元素定位

    元素定位就是通过元素的信息或元素层级结构来定位元素 要使用Web自动化操作元素 必须首先找到此元素 1 元素定位方式 1 1 基于元素属性特有的定位方式 1 id element driver find element by id id i
  • Python入门习题(91)——OpenJudge百练习题:汉诺塔问题

    OpenJudge百练第4147号习题 汉诺塔问题 题目描述 解题思路 参考答案 测试用例 小结 题目描述 来源 OpenJudge网站 百练习题集 第4147号习题 要求 总时间限制 1000ms 内存限制 65536kB 描述 一 汉诺
  • 猎聘发布《2019年中国5G人才需求大数据报告》

    在今年2月于西班牙巴塞罗那举办的2019世界移动通信大会上 华为 小米 vivo等中国企业先后扎堆发布了自己的5G手机 更加凸现了本次大会 5G商用产品 这一亮点 与此同时 5G成为大众新的关注焦点 借此契机 中高端人才职业发展平台猎聘推出
  • OVAL学习笔记

    很多其它好文章 http blog csdn net aap159951 article details 51131937 OVAL由MITRE公司开发 是一种用来定义检查项 脆弱点等技术细节的一种描写叙述语言 OVAL相同使用标准的XML
  • Android图片设置点击事件,Android EditText中插入图片并响应点击事件

    import android os Bundle import android app Activity import android content Context import android util Log import andro
  • 第3章 R语言编程基础——基于R软件的传统计算(超详细)

    3 1 统计分析 多元统计分析常用的 R 包和函数 3 1 1 多元回归分析 随机误差 计量模型 案例分析 M2 的建模与预测 残差的五数 估计参数的回归值 标准差 t检验量 p value 单变量显著性检验 拟合优度和 F 检验 Resi
  • bnu1331 赈灾捐款 C语言版

    北京师范大学珠海分校 Judge Online of ACM ICPC 1331 赈灾捐款 C语言版 include
  • ubuntu18.04下的mysql创建表

    ubuntu18 04下的mysql创建表 MySQL创建数据表 错误排查 出现报错 百度的解决思路 实际操作 MySQL创建数据表 删除表 drop table h data 创建表 CREATE TABLE IF NOT EXISTS
  • 第9章、图像按钮ImageButton(从零开始学Android)

    在Android App应用中 默认的Button按钮尽管我们可以通过样式变成圆角 但有时感觉仍然不够美观 我们可以通过采用图像按钮ImageButton改善这种现状 今天我们就一起学习一下图像按钮的使用 知识点 图像按钮ImageButt
  • 【数据结构课设】 浮点数计算器

    一 简介 1 功能介绍 实数的计算 支持取对数 幂次 开方及加减乘除运算 2 模块设计 1 菜单界面 2 计算器功能简介 3 计算器功能实现 3 计算器功能实现方法 1 字符串读入用户的表达式 2 处理字符串 包括提取实数以及中缀转后缀 维
  • idea开发中git合并的代码,

    方法一 将master主分支 合并到 子分支dev上 1 当前如果在dev分支上 先提交dev分支的代码到本地 然后推送到服务器 2 然后切换分支到master主分支上 先更新master主分支的代码到本地 然后主分支就是最新代码了 3 再
  • python 安卓模拟点击_Android后台模拟点击探索(附源码)

    工作中我们需要自制一套工具 其中遇到需要模拟点击事件的需求 类似按键精灵的功能 支持后台持续运行 满足触发条件时完成点击 经过一番探索 一共整理出两种不同的方案 AccessibilityService 和 adb shell命令 读者可自