Hid 方法
Hid 把动作交给已连接的蓝牙板子发出。能用节点时优先 UiObject。Hid 适合游戏,或页面会拦截无障碍手势的场景。
板子连上后,手机会看到三条通道:
| 通道 | 系统里的设备 | 谁在用 |
|---|---|---|
| 触摸屏 | DeekeScript-0001 | 点击、滑动、找图后的点击 |
| 字母键盘 | DeekeScript-0001 Keyboard | 名字带 key_ 的方法,以及 keyDown / keyUp / keyPress / keyPress_code 里的字符、方向和修饰键。clear 也走这里 |
| 消费控制 | DeekeScript-0001 Consumer Control | back / back1 / home / recents / power / volUp / volDown / paste。这是功能键,不是在打字 |
key_ 前缀一律是字母键盘。key_paste 是 Ctrl+V。贴一段文字用 paste,它走消费控制。
type 不固定走一条通道:数字、字母、回车走字母键盘;空格、其他符号和中文整段走 paste。
keyPress / keyDown / keyUp 按 Android 键值分流。字符和方向走字母键盘。下面这些键值走消费控制,和对应的系统键是同一个键:Home 3、返回 4、最近任务 187、音量加 24、音量减 25、电源 26、菜单 82。直接写 back()、home() 更清楚。
先打开蓝牙权限并烧好板子,见 权限 和 Hid 烧录。和无障碍的差别见 模式介绍。
坐标原点在屏幕左上角,单位是像素,包含状态栏。连接成功后,引擎已经用手机当前屏幕的真实宽高设好坐标,脚本里一般不用再写 setXY。
if (!Access.hasBluetoothConnectionPermission()) {
Access.requestBluetoothConnectionPermission();
System.exit();
}
Hid.initBluetooth();
// 第二个参数是设备索引,从 0 开始。这里连接索引为 0 的板子。
// 同时配对了多个蓝牙时,改成要连接的那一块的索引。
if (Hid.connectAndWait(true, 0)) {
Hid.tap(500, 800);
}相近方法怎么选
| 你想做的事 | 用这个 | 不要用 |
|---|---|---|
| 返回上一页 | 先 back()。大约按住 40 毫秒。没反应再 back1(),它按住 150 毫秒 | 不要两个连着按,除非确认短按无效 |
| 设置点击用的屏幕宽高 | 不用设置。连接时已经按当前屏幕设好 | 只有坐标不是这块屏幕时才 setXY |
| 点一下 | tap(x, y) | 自己拼 touchDown 容易忘了抬起 |
| 直线滑 / 带弧度滑 | swipe / swipex | |
| 按 Android 键值 | keyPress(code),例如回车是 66 | |
| 按 HID 键盘用途号 | keyPress_code(usage),例如字母 a 是 0x04 | 不要把 Android 键值传给 _code |
| 退格 / 向后删除 | key_del 删光标前一个字;key_delete 删光标后一个字 | |
| 输入一串字 | type。纯字母数字逐键输入,中文走 paste | 中文不要用 key_abc |
| 把一段文字贴进输入框 | paste(text)。先写入剪贴板,再发消费控制里的粘贴键 | 不要用 key_paste。key_ 都是键盘,key_paste 是 Ctrl+V,部分手机会因此收起输入法 |
| 是否连上 | isConnected() 和 getConnectState() 是同一个结果 |
| 分组 | 方法 |
|---|---|
| 连接 | initBluetooth / connect / connectAndWait / ensureConnected / isConnected / getConnectState / getConnectedDevices / getName / disconnect |
| 点击滑动 | tap / press / longClick / doubleTap / tapRandom / swipe / swipex / touchDown / touchMove / touchUp |
| 图色联动 | tapImage / pressImage / tapColor / waitImage / waitColor / waitImageGone / clickText / waitText / waitTextGone / swipeUntilImage |
| 消费控制 | back / back1 / home / recents / power / volUp / volDown / paste |
| 字母键盘 | key_ 前缀的全部方法,以及 keyDown / keyUp / keyPress / keyDown_code / keyUp_code / keyPress_code。clear 也走键盘 |
| 按字符拆开 | type。数字、字母、回车走键盘;空格、符号和中文走 paste |
| 设备 | setXY / setRnd / setBattery / reg / reboot / ver |
| 原始数据 | sendData / getData / waitFor |
initBluetooth()
返回: {boolean} 蓝牙是否已打开,并且应用有连接权限
只检查蓝牙,不连接板子。返回 false 时先看权限和系统蓝牙开关。真正连接用 connect 或 connectAndWait。脚本里不要传 context,引擎自己保存上下文。
connect(autoconnect, index)
参数:
autoconnect {boolean}是否交给系统自动重连。省略时为trueindex {number}设备序号,从 0 开始。省略时为0
返回: {boolean} 是否已经连上,并且可以发指令
会等到连接结束或失败,最长大约 25 秒。先在已配对、名称以 DeekeScript- 开头的设备里按序号取;没有再扫描。第一次配对时,手机上可能弹出确认。找不到设备、配对失败或板子没有回应时返回 false。
连上之后会自动按当前屏幕宽高调用 setXY,不用再设一次。
if (Hid.connect(true, 0)) {
Hid.tap(500, 800);
}connectAndWait(autoconnect, index, timeoutMs)
参数:
autoconnect {boolean}同connect,省略时为trueindex {number}同connect,省略时为0timeoutMs {number}连上之后再确认的最长毫秒数,默认10000
返回: {boolean} 结束时是否处于已连接
在 connect 之外再等到 isConnected() 为真。三个参数都可以省略:Hid.connectAndWait() 就是连第 0 个设备。第一次配对的确认时间可能超过 timeoutMs,因为 connect 自己最多会等大约 25 秒。
ensureConnected()
返回: {boolean} 现在是否已连接
已经连着就直接返回 true。没连上则按默认参数调用 connectAndWait。找图、输入这类方法内部也会先走这一步。
isConnected()
返回: {boolean} 指令通道是否还在
和 getConnectState() 是同一实现。断开、重启板子或连接失败后为 false。
getConnectState()
返回: {boolean} 同 isConnected()
保留这个名字是为了和旧脚本兼容。新脚本写 isConnected() 即可。
getConnectedDevices()
返回: {BluetoothDevice|null} 当前连上的那一台;没连接时为 null
这里返回的是这一台设备,不是列表。
getName()
返回: {string} 当前设备名称,例如 DeekeScript-0001。没连接时是空字符串
disconnect()
返回: {boolean} 是否已断开脚本这边的连接
只断开本次连接。系统蓝牙里的配对还在,下次 connect 不用重新配对。要换描述符或让手机重新读取板子时,需要在系统蓝牙里取消配对。
tap(x, y)
参数:
x {number}横坐标,像素y {number}纵坐标,像素
返回: {boolean} 板子是否完成了这次按下再抬起
在该点按住大约 30 毫秒后抬起。停留时间可用 setRnd 改成一个随机区间。没连接或坐标发送失败时返回 false。
Hid.tap(500, 800);press(x, y, durationMs)
参数:
x {number}横坐标y {number}纵坐标durationMs {number}按住毫秒数,默认800
返回: {boolean} 按下和抬起是否都成功
先 touchDown,等到指定时间,再抬起。抬起失败时会再试 touchUp2。未连接时会先尝试连接。
Hid.press(500, 800, 1000);longClick(x, y)
参数:
x {number}横坐标y {number}纵坐标
返回: {boolean} 同 press
长按,内部就是 press(x, y, 800)。
doubleTap(x, y)
参数:
x {number}横坐标y {number}纵坐标
返回: {boolean} 两次点击是否都成功
在同一点 tap 两次,中间隔 80 毫秒。
tapRandom(x, y, rx, ry)
参数:
x {number}中心横坐标y {number}中心纵坐标rx {number}横向随机半径,默认5ry {number}纵向随机半径,默认5
返回: {boolean} 是否点到了随机出来的那个点
实际点击落在 [x-rx, x+rx]、[y-ry, y+ry] 里。半径小于等于 0 时该方向不偏移。
swipe(x1, y1, x2, y2, step, down_timeout, up_timeout, timeout, up_down_times)
参数:
x1 {number}起点横坐标y1 {number}起点纵坐标x2 {number}终点横坐标y2 {number}终点纵坐标step {number}每步大约走多少像素。越大越快。省略时在 20–51 之间随机down_timeout {number}按下后等多久再开始滑,毫秒。省略时在 100–180 之间随机up_timeout {number}滑到终点后等多久再抬起,毫秒。省略时在 100–180 之间随机timeout {number}每一步之间的间隔,毫秒。省略时在 8–15 之间随机up_down_times {number}默认1,只滑一次。大于 1 时,滑完后在终点再点次数 - 1下
返回: {boolean} 板子是否完成这次滑动
直线滑动。后面 5 个参数都可以省略。
Hid.swipe(540, 1600, 540, 600);swipex(x1, y1, x2, y2, radian, step, down_timeout, up_timeout, timeout, up_down_times)
参数:
x1 {number}起点横坐标y1 {number}起点纵坐标x2 {number}终点横坐标y2 {number}终点纵坐标radian {number}弯曲程度。轨迹中点会往垂直方向偏这么多像素,不是数学里的弧度。越大弯得越厉害,常用 10–100。省略时在 10–100 之间随机step/down_timeout/up_timeout/timeout/up_down_times同swipe
返回: {boolean} 板子是否完成这次曲线滑动
需要看起来更像手指划过时用它。只要直线,用 swipe。
Hid.swipex(540, 1600, 540, 600, 80);touchDown(x, y)
参数:
x {number}横坐标y {number}纵坐标
返回: {boolean} 是否已在该点按下
手指留下,不会自动抬起。后面必须 touchMove 或 touchUp,否则屏幕会一直处于按下。普通点击用 tap。
touchMove(x, y)
参数:
x {number}横坐标y {number}纵坐标
返回: {boolean} 是否已把按下的手指移到该点
调用前要先 touchDown。
touchUp(x, y)
参数:
x {number}横坐标y {number}纵坐标
返回: {boolean} 是否在这个点抬起
抬起位置用这里传入的坐标,不是最后一次移动的位置。
touchUp()
返回: {boolean} 是否在最后一次按下或移动的位置抬起
不传坐标时用这个。
touchUp2()
返回: {boolean} 三次抬起里是否至少有一次成功
touchUp() 之后手指还按着时用。press 在一次抬起失败时会自动再调它。
home()
走消费控制。
返回: {boolean} 是否发出 Home 键
回到桌面。按住大约 40 毫秒。
recents()
走消费控制。
返回: {boolean} 是否发出最近任务键
打开多任务。按住大约 40 毫秒。
back()
走消费控制。
返回: {boolean} 是否发出返回键
按住大约 40 毫秒后松开,相当于点一下返回。日常返回用这个。
Hid.back();back1()
走消费控制,和 back() 是同一个键。
返回: {boolean} 是否发出按住更久的返回键
和 back() 是同一个返回键,按住时间是 150 毫秒。有的机型不认 40 毫秒的短按,页面没有回到上一页时再改用 back1()。两个方法的返回值只表示指令有没有发到板子,不表示界面已经返回。不要两个接连调用,除非你确认短按没有生效。
Hid.back();
// 页面没返回时,再执行:
// Hid.back1();power()
走消费控制。
返回: {boolean} 是否短按了电源键
按住大约 80 毫秒,用来亮屏或息屏。
power(time)
走消费控制,和 power() 是同一个键。
参数:
time {number}按住的毫秒数
返回: {boolean} 是否按住了这么久
时间拉长会打开关机界面。只想亮屏或息屏时不要传很大的数。
volUp()
走消费控制。
返回: {boolean} 是否发出音量加
按一下,大约 40 毫秒。
volDown()
走消费控制。
返回: {boolean} 是否发出音量减
按一下,大约 40 毫秒。
keyDown(code)
参数:
code {number}Android 键值,和KeyEvent一致。例如 A 是29,回车是66,退格是67
返回: {boolean} 是否已按下。键值没有对应的 HID 键时返回 false
只按下,不抬起。组合键时先按下修饰键,再按字母,最后分别抬起。字符、方向和修饰键走字母键盘。Home 3、返回 4、最近任务 187、音量加 24、音量减 25、电源 26、菜单 82 走消费控制。这些系统键直接写 back()、home() 更清楚。
keyUp(code)
参数:
code {number}同keyDown的 Android 键值
返回: {boolean} 是否已抬起
和某次 keyDown 配对使用。
keyPress(code)
参数:
code {number}同keyDown的 Android 键值
返回: {boolean} 是否完成按下再抬起
点一下该键,分流和 keyDown 相同。字母、数字、回车、方向键走字母键盘。Home、返回、最近任务、音量、电源、菜单走消费控制。
Hid.keyPress(66); // 回车
Hid.keyPress(29); // AkeyDown_code(code)
参数:
code {number}HID 键盘用途号,不是 Android 键值。a 是0x04,回车是0x28,退格是0x2A
返回: {boolean} 是否已按下该用途号
keyDown 不认识的键,而且你已经知道 HID 用途号时用这个。把 Android 键值传进来会按错键。
keyUp_code(code)
参数:
code {number}同keyDown_code的用途号
返回: {boolean} 是否已抬起
keyPress_code(code)
参数:
code {number}同keyDown_code的用途号
返回: {boolean} 是否完成一次按下再抬起
和 keyPress 的差别只在参数:这里直接发 HID 用途号,不经过 Android 键值转换。
keyUpAll()
返回: {boolean} 是否松开了当前还按着的键盘键和消费键
某个键卡住、页面一直在重复输入时调用。
key_select()
返回: {boolean} 是否发出全选(Ctrl+A)
key_copy()
返回: {boolean} 是否发出复制(Ctrl+C)
key_paste()
返回: {boolean} 是否发出键盘粘贴(Ctrl+V)
key_ 开头的方法都走字母键盘。这个方法按的是 Ctrl+V,光标要已经在输入框里。
往输入框里贴一段文字用 paste(text)。paste 走消费控制,不会调用 key_paste。Ctrl+V 会让部分手机把板子当成实体键盘,收起输入法,并弹出输入法和表情区域。
key_cat()
返回: {boolean} 是否发出剪切(Ctrl+X)
key_del()
返回: {boolean} 是否发出退格
删掉光标前面的一个字符,和键盘上的 Backspace 一样。
key_delete()
返回: {boolean} 是否发出向后删除
删掉光标后面的一个字符,和键盘上的 Delete 一样。输入框只认退格时用 key_del。
key_enter()
返回: {boolean} 是否发出回车
key_num(n)
参数:
n {number}0到9
返回: {boolean} 是否发出该数字键。超出 0–9 返回 false
只按一个数字键,不会输入多位数。多位数字用 type。
key_abc(n)
参数:
n {string}一个英文字母。大写会带上 Shift
返回: {boolean} 是否发出该字母。空字符串或不是字母时返回 false
只取第一个字符。整句用 type。中文用 type 或 paste,不要用这个方法。
setXY(x, y)
参数:
x {number}屏幕宽度,像素y {number}屏幕高度,像素
返回: {boolean} 板子是否已按这个宽高换算后面的坐标
参数是宽和高,不是要点击的位置。
连接成功时,引擎会用手机当前屏幕的真实宽高设一次。之后每次点击或滑动前,如果屏幕尺寸变了,也会再设一次。横屏、竖屏切换后直接点即可。
只有一种情况需要自己调用:你要的坐标系不是这块屏幕。例如脚本里的坐标来自另一台设备的分辨率。
// 一般不需要。下面是把坐标映射到 720x1280 的例子
Hid.setXY(720, 1280);
Hid.tap(360, 640);setRnd(x, y)
参数:
x {number}tap按下后停留的最短毫秒数y {number}最长毫秒数
返回: {boolean} 是否设置成功
默认最短和最长都是 30,所以 tap 大约按住 30 毫秒。设成一个区间后,每次 tap 的停留时间会在里面随机。y 小于 x 时按 x 固定停留。不影响 press 和 swipe 的时长。
Hid.setRnd(20, 80);setBattery(lv)
参数:
lv {number}电量百分比,会限制在 0–100
返回: {boolean} 板子是否改了蓝牙里显示的电量
只改手机蓝牙列表里看到的电量数字,不代表板子的真实电量。
reg(key)
参数:
key {string}要存进板子的注册字符串。空字符串表示清掉
返回: {boolean} 是否写入成功
一般业务脚本用不到。内容存在板子上,重启后还在。
reboot()
返回: {boolean} 板子是否接受了重启
板子会重启,当前连接断开。蓝牙名称不变。重启完成后需要重新 connect。
ver()
返回: {number} 板子固件版本号。查询失败返回 0
这是固件版本,不是 App 版本。
sendData(str)
参数:
str {string}发给板子自定义通道的文本
返回: {boolean} 板子是否收到。太长装不进一包时返回 false
这是自定义数据,不会变成点击或按键。和 getData 配合使用。
sendDataAwait(str, time)
参数:
str {string}同sendDatatime {number}等待板子确认的毫秒数,默认1000
返回: {boolean} 是否在时限内收到板子确认
getData(time)
参数:
time {number}最长等待毫秒数
返回: {string} 这段时间内新到的数据。超时返回 "超时",连接断了返回 "连接已断开"
getData()
返回: {string} 最近一次已经收到的数据。还没有数据时是空字符串
不会等待。要等到新数据用 getData(time) 或 waitFor。
waitFor(time, sleep)
参数:
time {number}最长等待毫秒数。0表示一直等到有数据或断开sleep {number}每次查看的间隔毫秒数
返回: {string} 新到的数据。超时返回 "超时",断开返回 "连接已断开"
waitFor(time)
参数:
time {number}最长等待毫秒数
返回: {string} 同上面。查看间隔默认 200 毫秒
waitFor()
返回: {string} 一直等到有数据或连接断开
找图、找色、输入
这些方法在没连接时会先 ensureConnected()。找图找色要先有截图权限,见 图片与颜色。识别细节见 图片、取色、文字识别。
tapImage(templateFile, threshold)
参数:
templateFile {string}模板图路径threshold {number}匹配阈值,默认0.8。越高越严
返回: {ImageMatch|null} 找到并点中则含 x、y、centerX、centerY、score、width、height。没找到或点击失败为 null
点击的是模板中心。
let m = Hid.tapImage("/sdcard/btn.png", 0.85);
if (m) {
console.log(m.centerX, m.centerY, m.score);
}pressImage(templateFile, durationMs, threshold)
参数:
templateFile {string}模板图路径durationMs {number}按住毫秒数,默认800threshold {number}匹配阈值,默认0.8
返回: {ImageMatch|null} 找到并按住则为匹配结果,否则 null
tapColor(color, tolerance)
参数:
color {string}rgba、rgb或#RRGGBBtolerance {number}每个颜色通道允许的偏差,默认0
返回: {Point|null} 找到并点中则含 x、y,否则 null
点的是这块颜色区域的中心。
let p = Hid.tapColor("#3480F8", 10);waitImage(templateFile, timeoutMs, intervalMs, threshold)
参数:
templateFile {string}模板图路径timeoutMs {number}最长等待,默认10000intervalMs {number}每次截屏间隔,默认500threshold {number}匹配阈值,默认0.8
返回: {ImageMatch|null} 图出现时的匹配结果。超时为 null
只等待,不点击。
waitColor(color, timeoutMs, intervalMs, tolerance)
参数:
color {string}颜色timeoutMs {number}最长等待,默认10000intervalMs {number}间隔,默认500tolerance {number}通道容差,默认0
返回: {Point|null} 颜色出现时的位置。超时为 null
waitImageGone(templateFile, timeoutMs, intervalMs, threshold)
参数:
templateFile {string}模板图路径timeoutMs {number}最长等待,默认10000intervalMs {number}间隔,默认500threshold {number}匹配阈值,默认0.8
返回: {boolean} 图消失则为 true。到时还在则为 false
clickText(keyword, timeoutMs, mode)
参数:
keyword {string}要找的文字timeoutMs {number}最长等待,默认10000mode {string}contains(默认)、exact或regex
返回: {Rect|null} 点中后返回文字区域。超时或点击失败为 null
用 OCR 找到文字,再点它的中心。
let rect = Hid.clickText("登录", 5000);
Hid.clickText("确定", 5000, "exact");waitText(keyword, timeoutMs, intervalMs, mode)
参数:
keyword {string}文字timeoutMs {number}最长等待,默认10000intervalMs {number}间隔,默认500mode {string}同clickText,默认contains
返回: {object|null} 出现时含 text、rect、confidence。超时为 null
只等待,不点击。
waitTextGone(keyword, timeoutMs, intervalMs, mode)
参数:
keyword {string}文字timeoutMs {number}最长等待,默认10000intervalMs {number}间隔,默认500mode {string}同clickText
返回: {boolean} 文字消失则为 true
swipeUntilImage(x1, y1, x2, y2, templateFile, maxTimes, threshold)
参数:
x1 {number}y1 {number}滑动起点x2 {number}y2 {number}滑动终点templateFile {string}模板图路径maxTimes {number}最多滑多少次,默认10threshold {number}匹配阈值,默认0.8
返回: {ImageMatch|null} 图出现时的匹配结果。滑满次数还没有则为 null
每次滑动后截屏查找。找到后不再滑,也不会自动点击。
let m = Hid.swipeUntilImage(500, 1500, 500, 500, "/sdcard/item.png", 8, 0.8);
if (m) {
Hid.tap(m.centerX, m.centerY);
}type(text)
参数:
text {string}要输入的内容
返回: {boolean} 是否全部发出。空字符串返回 true
数字和英文字母逐键输入,大写字母会带 Shift。换行发回车。空格和其他符号走 paste。含中文或非 ASCII 时,整段都走 paste。paste 使用消费控制,不按键盘上的 Ctrl+V。光标需要已经在输入框里。
Hid.type("hello");
Hid.type("你好世界");paste(text)
参数:
text {string}写入剪贴板的内容
返回: {boolean} 是否发出了消费控制里的粘贴键
先 setClip,大约 50 毫秒后再发消费控制粘贴键。不调用 key_paste,也不发送键盘上的 Ctrl+V。key_ 前缀的方法才走字母键盘。
clear()
返回: {boolean} 全选和删除是否都成功
走字母键盘:先 key_select(Ctrl+A),再 key_del。退格失败时再试一次 key_delete。用来清空当前输入框。
