AAIS
概述
AAI 脚本(AAIS)是建立在 AAI 的 FindNode 之上的非常小的脚本,它具有非常简单的语法和几十个命令,AAIS 并不是复杂的 JS/REST API 的替代品,它适用于编写简单的测试或临时脚本。AAIS 解析器会在执行过程中将命令转换为 JavaScript(以及 FindNode 命令)。它具有与 JavaScript 不同的几个属性:
多行支持
AAIS 支持基本的多行支持。有两种方法可以实现多行支持:
"<文本 1>\
<文本 2>"
这适用于所有双引号,在行尾处的 "\" 允许跨多行连接文本。例如:
{var a = 1, b = 2}
print "The sum of \
${a} and \
${b} is \
${a+b}"
将在日志文件中显示 "The sum of 1 and 2 is 3"。
{ <query/action>
<query/action> }
这主要适用于 "sendAai",复杂的命令可能需要多个参数来完成任务。不匹配的 "{}" 或 "[]" 将导致脚本错误。
{var tp = "all"}
// 7 lines command
sendAai {actions:[
"getCount(+TP:\
${tp})",
"getCount(+TP:more)",
"getCount(+TP:basic)",
"getCount(+TP:reduced)"
]}
{
var output = getOutput();
firstNum = output.list[0].count;
lastNum = output.list[output.list.length -1].count;
log("firstNum = " + firstNum);
log("lastNum = " + lastNum);
}
print "From ${tp} template number of ${firstNum} reduced to ${lastNum}"
Log File:
2023-01-13 06:31:30 info system {name: 'samsung-SM-S908U1', object: 'device@1237418919', value: {count: 4, list: [{count: 162},{count: 69},{count: 64},{count: 63}]}, error: {}}
2023-01-13 06:31:30 info system firstNum = 162
2023-01-13 06:31:30 info system lastNum = 63
2023-01-13 06:31:30 info system From all template nodes number of 162 reduced to 63
注意
AAIS 命令
点击/长按
在屏幕上点击或长按查询字符串或文本。如果未找到查询或文本,脚本将停止执行。有关查询语法,请参阅 FindNode 用户指南。如果在 "寻找" 或 "等待" 命令之后的 "点击" 没有参数,则会点击“查找 ” 命令的第一个匹配项。
用法:
点击/长按 <text|query>
示例:
点击 "T:About phone||OX:1"
长按 "Information"
// 查找并点击 John
寻找 "John"
点击
等待 "Click for detail"
点击
启动/重启
启动或重启一个应用程序,重启会强制关闭应用程序并重新启动。如果找不到应用程序,脚本将停止执行。
用法:
启动/重启 <包名>
启动/重启 <应用程序名称>
示例:
启动 "com.raider.skype"
等待 "Favorites"
重启 "Skype"
等待
该命令会等待匹配项被找到或超时。如果超时,脚本将停止执行。如果未指定超时时间,默认为5000毫秒。有关查询语法,请参阅 FindNode 用户指南。
用法:
等待 <text|query>
等待 <text|query>, <timeout in milliseconds>
示例:
等待 "Finish"
等待 "R:.icon_done", 20000
文本
向文本字段输入文本,文本字段通过位置或初始提示字符串进行定位,如果找不到文本字段,脚本将停止执行。为了准确地根据位置定位文本字段,文本字段将根据从左上到右下的位置进行排序。
用法:
文本 <text> // 在第一个文本字段中输入文本
文本 <text>, <position> // 位置从0开始 - 第一个文本字段,1 - 第二个文本字段,...
文本 <text>, <hint> // 输入具有初始提示字符串的文本字段
示例:
文本 "Hello world"
文本 "Hello world", "Please input a message"
文本 "Hello world", 2
按键
按下一个键码(和可选的元状态)或键码名称,错误的键码名称将停止脚本的执行。
用法:
按键 <keycode name>
按键 KeyCode, <keycode>
按键 KeyCode, <keycode>, <meta state>
示例:
按键 Home
按键 KeyCode, 47, 1
请参考https://developer.android.com/reference/android/view/KeyEvent了解所有的键码名称。
以下是常用的键码名称(不区分大小写):
Enter
Back
Home
Back_space
Search
Power
Tab
寻找
根据屏幕上的方向滚动,直到找到匹配项,如果找不到,脚本将停止并显示错误。默认方向为“down”。
用法:
寻找 <text|query> [<direction>]
有四个方向:
示例:
寻找 "${name}"
寻找 "T:OK||C:.Button"
click
执行
执行另一个 AAIS 或 JavaScript 脚本,如果脚本生成错误,则会停止执行。默认路径为 Documents\scripts 目录。如果扩展名为 ".js",则加载为 JavaScript;如果扩展名为 ".tst",则加载为 AAIS。通过 "执行" JavaScript 可以提供函数/常量以供 AAIS 集成,或执行无法在 AAIS 中完成的任务。
用法:
执行 <文件路径和文件名>
示例:
执行 "aais\\skype.tst"
执行 "C:\\aais\\skype.tst"
执行 "nestLib.js"
打印
将文本字符串打印到日志文件中。
用法:
打印 <文本>
延迟
临时暂停脚本执行指定的毫秒数。
用法:
延迟 <毫秒数>
示例:
延迟 10000
选择
用于点击复选框,接受 true/false。"false" 将取消勾选,"true" 将设置勾选。
用法:
选择 <文本|查询> true|false
示例:
选择 "C:.Checkbox&&T:Milk"
进度
用于设置滑块的值,如 ".SeekBar" 的类名。在 FindNode 中显示为 "rangeInfo"(getNodes(RI)),它具有整数或浮点数类型,并具有最小值和最大值。确保值在范围内。
用法:
进度 <query> <整数或浮点数值>
示例:
进度 "T:Notifications&&OY:1&&OX:1", 1200
get
从 FindNode 获取信息。它有 4 种类型的 get(在需要时可能会添加更多),参数是可选的。返回值将保存到日志文件中,并可以从 JavaScript 的 "getOutput()" 中获取。
用法:
get <查询>, <类型>
类型:
示例:
exec "volumeLib.js"
get "T:Notifications&&OY:1&&OX:1", "node"
{
var rangeInfo = getOutput().list[0].rangeInfo;
var current = rangeInfo.current;
var min = rangeInfo.min;
var max = rangeInfo.max;
var mid = (max-min)/4;
if (current > mid*3) {
tooLoud(getDevice(), current);
} else if (current < mid) {
tooSoft(getDevice(), current);
}
}
sendAai
sendAai 使用 "device.sendAai" 向 FindNode 发送命令,返回值将保存到日志文件中,并可以从 JavaScript 的 "getOutput()" 中获取。任何失败(从 FindNode 接收到 null)都会导致脚本停止。目前,AAIS 不允许每个命令多行输入,下一个版本将支持多行命令。
用法:
sendAai {<查询或动作>}
示例:
sendAai {actions:[
"openAndroidSetting(application development settings)",
"scrollIntoView(T:Window animation scale)",
"click",
"click(+T:Animation scale .5x)",
"sendKey(Back)",
"sendKey(Back)"]}
与 JavaScript 的集成
AAIS 是一个解析器,它读取以 ".tst" 扩展名的 AAIS 脚本并生成用于执行的 JavaScript,与 JavaScript 的集成很简单,将 JavaScript 代码放在 "{}" 中。要在 AAIS 和 JavaScript 之间传递数据:
例如:
{ <JavaScript> 代码 }
或
{
<JavaScript 代码>
}
示例:
exec "phoneLib.js"
get "T:Android version&&OY:1", "text"
{
setVersion(getDevice(), getOutput().retval);
}
假设 "phoneLib.js" 中定义了 "setVersion()" 函数。
由于 AAIS 脚本可以在多个设备上运行,所有的 JS 命令块将逐个设备执行多次。因此,在上面的示例中,如果选择了 20 个设备,将会执行 20 次 "setVersion"。"getDevice()" 将返回 20 个不同的设备。
您可以先执行(加载)一个 JS 库(带有常量或函数):
exec <library>.js
JS 代码块将与 "exec" 处于相同的上下文中,因此您可以方便地访问它们。
此外,AAIS 还提供了几个函数:
exec "phoneLib.js"
get "T:Model name&&OX:1", "text"
{ saveVar("modelName", getOutput().retval) }
get "T:Model number&&OX:1", "text"
{ saveVar("modelNumber", getOutput().retval) }
get "T:IMEI&&OX:1", "text"
{
saveInfo(getDevice(),
loadVar("modelName"),
loadVar("modelNumber"),
getOutput().retval);
}
saveVar 和 loadVar 与 getDevice() 相关,因此 loadVar 将始终返回相同设备上的 saveVar,彼此不会干扰。
如果您只想执行一次而不是每个设备都执行,请使用 "doOnce()"。
exec "runLib.js"
get "T:Run ID", "text"
{
if (doOnce()) {
saveDatabase(getOutput().retval);
}
}
函数
AAIS JavaScript 中内置了几个函数:
getDevice() → device
将返回当前设备。
getDevices() → 设备数组
将返回所有选定的设备。
saveVar(<name>, <value>)
将使用指定的名称存储变量,该变量存储在 getDevice() 的范围内。
loadVar(<name>) → <value>
将加载指定名称的变量并返回其值。该值仅在使用 saveVar() 与相同的 getDevice() 存储时可见。
saveGlobalVar(<name>, <value>)
将在由名称标识的全局范围中存储变量,任何设备都可以访问它。
loadGlobalVar(<name>) → <value>
将返回由名称标识的全局范围。
doOnce() → true|false
第一次运行时返回 true,随后的运行将返回 false。
getOutput() → 来自 FindNode 的输出
此函数仅适用于 "get" 和 "sendAai",JavaScript 代码块需要紧接在 "get" 或 "sendAai" 命令之后,对其他命令使用 "getOutput" 将生成错误并停止脚本执行。有关返回格式,请参阅日志文件中的内容。
getArg() → 字符串数组
Runner 允许用户将参数作为字符串数组传递给 JavaScript。结合变量替换,可以在运行时创建查询/操作。当支持命令行模式时,getArg() 将返回命令模式下的参数。Runner 中有一个按钮用于设置参数。
log(<message>)
此函数类似于 AAIS 的 "print" 函数,它将消息附加到现有的 Runner 日志文件中。
throw(<message>)
由于 AAIS 被转换为 JavaScript,您可以使用 throw(<message>) 来停止执行。错误消息将被记录并显示给用户。
"…${<expression>}…"
模板文字中的表达式允许任何双引号包含 ${…} 包围的 JavaScript 表达式。对于变量替换或简单的 JavaScript 表达式非常有用。
AAIS 示例
此示例打开特斯拉应用程序并检索汽车的 VIN 和里程:
exec "teslaLib.js"
open "Tesla"
find "T:VIN:"
get "T:VIN:&&OX:1", "text"
{ saveVar("vin", getOutput().retval) }
get "T:/[0-9,]+ miles/", "text"
{ saveMileage(new Date(), loadVar("vin"), getOutput().retval) }
print "Done"
根据索引号打开应用程序,可以从 JavaScript 传递 "app" 到 AAIS:
{
var apps = ["Skype", "Whatsapp", "Telegram"];
var arguments = getArg();
var app = apps[0];
if (arguments.length > 0) {
var appNum;
if(isNaN(appNum = parseInt(arguments[0]))) {
throw "Need a number;"
}
if (appNum < 1 || appNum > apps.length) {
throw "Option out of range";
}
app = apps[appNum-1];
}
}
open "${app}"
print "${app} opened"
创建脚本
将脚本保存为带有 ".tst" 扩展名的文本文件,例如 skype.tst,或者您可以使用录制和回放功能在 AAIS 中录制脚本(需要选择对象模式)。
运行脚本
在 Runner 中运行 AAIS 脚本,结果将存储在 "Task" 中: