Android 模拟点击
Android 模拟点击
1.通过代码的方式实现
通过模拟MotionEvent的方式实现
//----------------模拟点击---------------------
private void simulateClick(View view, float x, float y) {long downTime = SystemClock.uptimeMillis();final MotionEvent downEvent = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, x, y, 0);downTime += 1000;final MotionEvent upEvent = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_UP, x, y, 0);view.onTouchEvent(downEvent);view.onTouchEvent(upEvent);downEvent.recycle();upEvent.recycle();
}public void setMouseClick1(int x, int y) {MotionEvent evenDownt = MotionEvent.obtain(System.currentTimeMillis(),System.currentTimeMillis() + 100, MotionEvent.ACTION_DOWN, x, y, 0);dispatchTouchEvent(evenDownt);MotionEvent eventUp = MotionEvent.obtain(System.currentTimeMillis(),System.currentTimeMillis() + 100, MotionEvent.ACTION_UP, x, y, 0);dispatchTouchEvent(eventUp);evenDownt.recycle();eventUp.recycle();
}
通过模拟Instrumentation测试的方式实现
new Thread(() -> {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));
}).start();
Instrumentation
不能在主线程中使用
java.lang.RuntimeException: This method can not be called from the main application thread
通过模拟adb命令的方式实现
try {List<String> orders = new ArrayList<>();orders.add("input");orders.add("tap");int[] location = new int[2];view.getLocationInWindow(location);int x = location[0];int y = location[1];orders.add("" + (x + 10));orders.add("" + (y + 10));new ProcessBuilder(orders).start();
} catch (IOException e) {e.printStackTrace();
}
相当于执行 adb 的命令,input tap x y
x和y是坐标
2.通过adb的方式实现
一共就2步
1.打开终端,输入adb shell
2.执行模拟点击命令
1、查看命令
MassageRobotTCL>adb shell
Lacus_12:/ # input
Usage: input [] [-d DISPLAY_ID] […]
The sources are:
dpad
keyboard
mouse
touchpad
gamepad
touchnavigation
joystick
touchscreen
stylus
trackball
-d: specify the display ID.
(Default: -1 for key event, 0 for motion event if not specified.)
The commands and default sources are:
text (Default: touchscreen)
keyevent [–longpress] … (Default: keyboard)
tap (Default: touchscreen)
swipe [duration(ms)] (Default: touchscreen)
draganddrop [duration(ms)] (Default: touchscreen)
press (Default: trackball)
roll (Default: trackball)
motionevent <DOWN|UP|MOVE> (Default: touchscreen)
Lacus_12:/ #
Lacus_12:/ # input tap 1002 922
Lacus_12:/ # input tap 1002 900
Lacus_12:/ # input keyevent 4
2、getevent -h 用法说明
shell@hwH60:/ $ getevent -h Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]-t: show time stamps-n: don't print newlines-s: print switch states for given bits-S: print all switch states-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)-d: show HID descriptor, if available-p: show possible events (errs, dev, name, pos. events)-i: show all device info and possible events-l: label event types and names in plain text-q: quiet (clear verbosity mask)-c: print given number of events then exit-r: print rate events are received
[-t] 参数显示事件的时间戳
[-n] 取消事件显示时的换行符
[-s switchmask] 得到指定位的开关状态
[-S] 得到所有开关的状态
[-v [mask]] 根据mask的值显示相关信息
[-p] 显示每个设备支持的事件类型和编码
[-q] 只显示事件数据
[-c count] 只显示count次事件的数据
[-r] 显示事件接收频率
3、getevent -p 显示出来当前系统存在的所有input设备,并且把每个设备支持的事件类型以及编码
shell@hwH60:/ $ getevent -padd device 1: /dev/input/event2name: "hi6421_on"events:KEY (0001): 0074 input props:<none>
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 2: /dev/input/event4name: "huawei,touchscreen"events:KEY (0001): 003b 003c 003d 003e 003f 0040 0041 0042 0043 0044 0057 00bd 00be 00bf 00c0 00c1 0145 014a ABS (0003): 0000 : value 0, min 0, max 1079, fuzz 0, flat 0, resolution 00001 : value 0, min 0, max 1919, fuzz 0, flat 0, resolution 00018 : value 0, min 0, max 255, fuzz 0, flat 0, resolution 00030 : value 0, min 0, max 15, fuzz 0, flat 0, resolution 00035 : value 0, min 0, max 1079, fuzz 0, flat 0, resolution 00036 : value 0, min 0, max 1919, fuzz 0, flat 0, resolution 00039 : value 0, min 0, max 15, fuzz 0, flat 0, resolution 0003a : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0input props:INPUT_PROP_DIRECT
add device 3: /dev/input/event0name: "mhl_rcp_dev"events:KEY (0001): 0002 0003 0004 0005 0006 0007 0008 0009 000a 000b 000e 001c 0034 003b 003c 003d 003e 003f 0067 0069 006a 006c 0071 0072 0073 0077 0080 008b 009e 009f 00a1 00a4 00a5 00a7 00a8 00ae 00c8 00c9 00cf 00d0 00d5 00e8 0161 0163 0192 0193 019c input props:<none>
could not get driver version for /dev/input/mice, Not a typewriter
add device 4: /dev/input/event1name: "hisi_gpio_key.14"events:KEY (0001): 0072 0073 input props:<none>
add device 5: /dev/input/event3name: "hi3630_hi6401_CARD Headset Jack"events:KEY (0001): 0072 0073 00e2 SW (0005): 0002 0004 input props:<none>
4、getevent 查看输入设备和查看事件
打印输出log日志,等待输入设备,我们触摸屏幕或是手机物理按键,便会看到这里的变化
shell@hwH60:/ $ getevent例如:
/dev/input/event0: 0001 014a 00000001
/dev/input/event0: 0003 0000 000000f6
/dev/input/event0: 0003 0001 000002ed
/dev/input/event0: 0003 0035 000000f6
/dev/input/event0: 0003 0036 000002ed
/dev/input/event0: 0003 0032 00000001
/dev/input/event0: 0003 0039 00000000
/dev/input/event0: 0003 003a 00000043
/dev/input/event0: 0000 0002 00000000
他们四个参数对应的是device type code value
device:指的是处理触摸和按键的输入设备。
type:指的是事件类型,EV_SYN [0000] (同步事件),EV_KEY [0001] (按键事件),EV_ABS [0003] (绝对值事件)
code 指的是前面type代表的事件中支持的编码。
value 指的是值。
例如:需要模拟一次点击BACK键,模拟点击的功能通常都是使用 /dev/input/event0 这个输入设备,back键的类型为 0001(按键事件),BACK的编码为 0x9e 转换为十进制后即158
注意的是在getevent中code显示的是十六进制,而sendevent时需要用十进制
那我们输入如下命令即可模拟一次BACK键的按下和弹起:
adb shell sendevent /dev/input/event0 1 158 1
adb shell sendevent /dev/input/event0 1 158 0
5、input keyevent 命令
先列举 input keyevent 几个比较常用的code值:
input keyevent 3 // Homeinput keyevent 4 // Backinput keyevent 19 //Upinput keyevent 20 //Downinput keyevent 21 //Leftinput keyevent 22 //Rightinput keyevent 23 //Select/Okinput keyevent 24 //Volume+input keyevent 25 // Volume-input keyevent 82 // Menu 菜单
例如:
点击back键
shell@hwH60:/ $ input keyevent 3
input text 命令
输入框输入内容的。后面参数为 “字符串”,例如输入”helloworld”字符串
shell@hwH60:/ $ input text "helloworld!"
input tap 命令
模拟单击事件 后面参数为: x y ,例如点击(168,252)位置
shell@hwH60:/ $ input tap 168 252
input swipe 命令
此命令为滑动事件。例如:从 30 10 滑动到 30 100
shell@hwH60:/ $ input swipe 30 10 30 100
Android代码实现,注意需要root
private void execShellCmd(String cmd) { try { // 申请获取root权限,这一步很重要,不然会没有作用 Process process = Runtime.getRuntime().exec("su"); // 获取输出流 OutputStream outputStream = process.getOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream( outputStream); dataOutputStream.writeBytes(cmd); dataOutputStream.flush(); dataOutputStream.close(); outputStream.close(); } catch (Throwable t) { t.printStackTrace(); }
}
execShellCmd("getevent -p");
execShellCmd("sendevent /dev/input/event0 1 158 1");
execShellCmd("sendevent /dev/input/event0 1 158 0");
execShellCmd("input keyevent 3");//home
execShellCmd("input text 'helloworld!' ");
execShellCmd("input tap 168 252");
execShellCmd("input swipe 100 250 200 280");
<uses-permission android:name = "android.permission.INJECT_EVENTS"/>
3.关于x、y坐标的获取
获取view的相对于屏幕中的坐标
要获取View相对于屏幕的坐标,可以使用getLocationOnScreen()方法。以下是一个示例代码:
View view = findViewById(R.id.my_view);int[] location = new int[2];
view.getLocationOnScreen(location);int x = location[0];
int y = location[1];
在上述示例中,首先获取要获取坐标的View对象。然后创建一个长度为2的整型数组。接下来,使用getLocationOnScreen()方法将View的相对于屏幕的坐标存储到数组中。最后,通过数组的元素获取x和y坐标。请注意,x和y坐标是相对于屏幕的像素位置,以左上角为原点。
如果要获取View相对于父容器的坐标,可以使用getLocationInWindow()方法。以下是一个示例代码:
View view = findViewById(R.id.my_view);int[] location = new int[2];
view.getLocationInWindow(location);int x = location[0];
int y = location[1];
在上述示例中,使用的方法和步骤与获取相对于屏幕的坐标相同,只是获取的是相对于父容器的坐标。请注意,x和y坐标是相对于父容器的像素位置,以左上角为原点。
这里的y坐标为什么和view.getY不一样?
对于获取View的坐标,getY()方法返回的是View相对于父容器(即包含该View的布局容器)的y坐标。而getLocationOnScreen()方法返回的是View相对于整个屏幕的坐标。
这两个方法返回的坐标值可能不同的原因是,View的坐标是相对于其父容器的坐标系的,而父容器在屏幕上的位置是可能发生变化的。当父容器发生位置变化时(例如滚动、动画等),View相对于父容器的坐标会发生相应的变化。而getLocationOnScreen()方法返回的是View相对于屏幕的坐标,不受父容器位置变化的影响。
因此,如果你需要获取View相对于屏幕的坐标,应该使用getLocationOnScreen()方法。如果需要获取View相对于父容器的坐标,可以使用getX()和getY()方法。请根据具体的需求选择合适的方法来获取坐标。
4.通过使用sendevent的方式实现
adb提供了控制手机的另一种实现: sendevent [device] [type] [code] [value]
eg:229就是menu的type值
sendevent /dev/input/event0 1 229 1
sendevent /dev/input/event0 1 229 0
这两句需要一起执行,因为一个点击事件包含down和up,不然不能执行操作。
这种方式不推荐,使用命令靠谱。除非你知道type值。
5.参考
Android代码模拟物理、屏幕点击事件 、APP内部自动点击
Android模拟点击的四种方式
Android模拟屏幕点击
相关文章:
Android 模拟点击
Android 模拟点击 1.通过代码的方式实现 通过模拟MotionEvent的方式实现 //----------------模拟点击--------------------- private void simulateClick(View view, float x, float y) {long downTime SystemClock.uptimeMillis();final MotionEvent downEvent MotionEve…...

css自学框架之选项卡
这一节我们学习切换选项卡,两种切换方式,一种是单击切换选项,一种是鼠标滑动切换,通过参数来控制,切换方法。 一、参数 属性默认值描述tabBar.myth-tab-header span鼠标触发区域tabCon.myth-tab-content主体区域cla…...
Element Plus组件库中的input组件如何点击查看按钮时不可编辑,点击编辑时可编辑使用setup
如果你正在使用 Vue 3 和 Composition API,你可以使用 setup 函数来实现 Element Plus 的 Input 组件在点击查看按钮时不可编辑,点击编辑按钮时可编辑的功能。 以下是一个使用 setup 的示例代码: <template><div><el-input …...

小米、华为、iPhone、OPPO、vivo如何在手机让几张图拼成一张?
现在很多手机自带的相册APP已经有这个拼图功能了。 华为手机的拼图 打开图库,选定需要拼图的几张图片后,点击底部的【创作】,然后选择【拼图】就可以将多张图片按照自己想要的位置,组合在一起。 OPPO手机的拼图 打开相册&#…...

物联网AI MicroPython传感器学习 之 WS2812 RGB点阵灯环
学物联网,来万物简单IoT物联网!! 一、产品简介 ws2812是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同,每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路&a…...
【GPU常见概念】GPU常见概念及分类简述
随着大模型和人工智能的爆火,大家对GPU的关注持续上升,本文简单简述下GPU经常用的概念。 GPU(图形处理器),又称显示核心、视觉处理器、显示芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备&…...

JVM篇---第九篇
系列文章目录 文章目录 系列文章目录一、什么是指针碰撞?二、什么是空闲列表三、什么是TLAB? 一、什么是指针碰撞? 一般情况下,JVM的对象都放在堆内存中(发生逃逸分析除外)。当类加载检查通过后࿰…...
探索 GAN 和 VAE 之外的 NLP 扩散模型
介绍 扩散模型最近引起了极大的关注,特别是在自然语言处理(NLP)领域。基于通过数据扩散噪声的概念,这些模型在各种NLP任务中表现出了卓越的能力。在本文中,我们将深入研究扩散模型,了解其基本原理,并探讨实际应用、优势、计算注意事项、扩散模型在多模态数据处理中的相…...
发现很多人分不清 jwt session token 的区别?
1. JWT(JSON Web Token) 1.1 什么是JWT? JWT,全称为JSON Web Token,是一种用于在网络上安全传输信息的开放标准。它的设计初衷是用于跨域通信,在不同域之间传递声明性信息。JWT是一种自包含的令牌&#x…...

GPT系列论文解读:GPT-3
GPT系列 GPT(Generative Pre-trained Transformer)是一系列基于Transformer架构的预训练语言模型,由OpenAI开发。以下是GPT系列的主要模型: GPT:GPT-1是于2018年发布的第一个版本,它使用了12个Transformer…...

神经网络中的知识蒸馏
多分类交叉熵损失函数:每个样本的标签已经给出,模型给出在三种动物上的预测概率。将全部样本都被正确预测的概率求得为0.70.50.1,也称为似然概率。优化的目标就是希望似然概率最大化。如果样本很多,概率不断连乘,就会造…...

jmeter利用自身代理录制脚本
在利用代理录制脚本时一定要安装java jdk,不然不能录制的。 没有安装过java jdk安装jmeter后打开时会提示安装jdk,但是mac系统中直接打开提示安装jdk页面后下载的java并不是jdk(windows中没有试验过,笔者所说的基本全部指的是在ma…...

【漏洞复现】时空智友企业流程化管控系统 session泄露
漏洞描述 时空智友企业流程化管控系统 session 泄露 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用…...
获取泛型的类型
示例一:获取父类的泛型的类型 public class Emp<T, Q> {class Stu extends Emp<String, Integer> {}Testvoid fun() {final Type type Emp.class.getGenericSuperclass();final ParameterizedType parameterizedType (ParameterizedType) type;Syste…...
[Python进阶] Pyinstaller打包问题
5.9 Pyinstaller打包问题 5.9.1 找不到指定的模块 Pyinstaller在进行打包时,会解析打包的Python文件,自动寻找py源文件的依赖模块。但是Pyinstaller解析模块时可能会遗漏某些模块,这个时候就会报错:No Module named xxx。 如果是…...

计算机竞赛 题目:基于机器视觉opencv的手势检测 手势识别 算法 - 深度学习 卷积神经网络 opencv python
文章目录 1 简介2 传统机器视觉的手势检测2.1 轮廓检测法2.2 算法结果2.3 整体代码实现2.3.1 算法流程 3 深度学习方法做手势识别3.1 经典的卷积神经网络3.2 YOLO系列3.3 SSD3.4 实现步骤3.4.1 数据集3.4.2 图像预处理3.4.3 构建卷积神经网络结构3.4.4 实验训练过程及结果 3.5 …...

竞赛选题 机器学习股票大数据量化分析与预测系统 - python 竞赛选题
文章目录 0 前言1 课题背景2 实现效果UI界面设计web预测界面RSRS选股界面 3 软件架构4 工具介绍Flask框架MySQL数据库LSTM 5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 机器学习股票大数据量化分析与预测系统 该项目较为新颖&am…...

智慧驿站:为城市带来全新智慧公厕未来形态
随着城市发展和科技进步的不断推进,智慧公厕逐渐成为城市规划和公共设施建设的重要组成部分。而集合了创意的外观设计、全金属结构工艺、智慧公厕、自动售货、共享设备、广告大屏、小型消防站、小型医疗站,并能根据需要而灵活组合的智慧驿站成为其中重要…...
Java获取汉字首字母
Java获取汉字的首字母,例如:中国香港,则返回ZGXG;Tom 中国欢迎你,则返回 TOM ZGHYN,如果为英文,则返回英文的大写形式,传空字符串则什么也不返回。 其中需要引用的maven依赖…...

基于or-tools的人员排班问题建模求解(JavaAPI)
使用Java调用or-tools实现了阿里mindopt求解器的案例(https://opt.aliyun.com/platform/case)人员排班问题。 这里写目录标题 人员排班问题问题描述数学建模编程求解(ortoolsJavaAPI)求解结果 人员排班问题 随着现在产业的发展&…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...