AAIS

概述

AAI Script (AAIS) 是建立在 AAI 的 FindNode 之上的非常小的脚本,它有一个非常简单的语法和十几个命令,AAIS 不是复杂的 JS/REST API 的替代品,它对编写简单的测试非常有帮助并让我们远离复杂的脚本。AAIS 解析器将在执行期间将命令转换为 JavaScript(和 FindNode 命令)。它有几个不同于 JavaScript 的属性:

  • 由于它建立在 FindNode 之上,因此它继承了 FindNode 的属性:
    • 基于对象,而不是基于坐标。
    • 100%兼容FindNode的查询语言。
    • 支持混合设备环境中的脚本(不同的分辨率和大小)。
    • 使用"寻找"替换设备相关的页面向下/向上。"寻找"将滚动直到找到节点。
  • 没有条件,没有循环,没有变量(只有JS变量),不适合复杂的脚本。
  • 任何失败/错误都将导致脚本停止。
  • 它被构建为在多个设备上运行,用户选择一组设备(1 到 100),它将以每个设备一个线程启动脚本。
  • 同时支持 MDCC(多设备控制中心)和 WDM(Windows 桌面模式)。
  • 与 JavaScript 良好集成,JavaScript 代码块在任何换行处都包含在"{}"中。将根据设备计数循环多次。
  • "print"、"get"和"sendAai"的任何错误消息或输出都将保存在日志文件中。JavaScript log() 也可以保存到日志文件中。
  • "get"和"sendAai"允许 JavaScript 获取输出 (getOutput())。
  • AAIS 脚本可以执行 JavaScript 的模板文字,允许通过 ${<expression>} 进行 JS 表达式或变量替换。
  • "//"为注释符,"//"后的内容将被忽略。
  • AAIS 支持每个命令基本多行:

多行支持

AAIS 支持基本的多行支持。有两种方法可以进行多行支持:

"<文本 1>\
<文本 2>"

这适用于所有双引号,行尾的"\"将允许跨多行连接文本。例如:

{var a = 1, b = 2}
print "The sum of \
${a} and \
${b} is \
${a+b}"

将在日志文件中显示"1 和 2 的总和为 3”。

{ <查询/操作>
<查询/操作> }

这主要适用于"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" 
// find and click John
寻找 "John"
点击
等待 "Click for detail"
点击

启动/重启

打开或重启应用程序,重启将强制关闭应用程序并重新启动。如果未找到应用程序,脚本将停止。

用法:

启动/重启 <package name>
启动/重启 <app name>

例子:

启动 "com.raider.skype"
等待 "Favorites"
	
重启 "Skype"

等待

该命令一直等到找到匹配项或超时到期。如果超时到期,脚本将停止。如果不指定超时,默认为 5000 毫秒。有关查询语法,请参阅 FindNode 用户指南。

用法:

等待 <text|query>
等待 <text|query>, <timeout in milliseconds>

例子:

等待 "Finish"
等待 "R:.icon_done", 20000

文本

在文本域中输入文本,文本域按位置或初始提示字符串定位,如果找不到文本域,脚本将报错停止。为了按位置准确定位文本字段,将根据文本字段位置从左上到右下对文本字段进行排序。

用法:

文本 <text> 	         // Enter text in the first text field
文本 <text>, <position>  // position starts with 0 – first text field, 1 – second text field, …
文本 <text>, <hint> 	 // Enter into the text field with the initial hint string

例子:

文本 "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

寻找

它将根据屏幕上的方向滚动,直到找到匹配项,如果找不到,脚本将因错误而停止。默认值为"向下”。

用法:

寻找 <text|query> [<direction>]

有4个方向:

  • "down": 从当前位置开始向下搜索(不指定默认)。
  • "up":从当前位置向上查找。
  • “fromTop”:从应用程序顶部开始向下滚动。
  • “fromBottom”:滚动到应用底部并向上搜索。

例子:

寻找 "${name}"
寻找 "T:OK||C:.Button"
click

执行

执行另一个 AAIS 或 JavaScript,如果脚本产生错误将停止。默认位于 Documents\scripts 目录中。如果扩展名是“.js”,它作为 JavaScript 加载,如果扩展名是“.tst”,它作为 AAIS 加载。“exec"JavaScript 要么为 AAIS 集成提供函数/常量,要么执行 AAIS 中无法完成的任务。

用法:

执行 <file path and filename>

例子:

执行 "aais\\skype.tst"
执行 "C:\\aais\\skype.tst"
执行 "nestLib.js"

打印

将文本字符串打印到日志文件。

用法:

打印 <text>

延迟

临时暂停指定毫秒的脚本执行。

用法:

延迟 <time in milliseconds> 

例子:

延迟 10000

选择

检查用于单击复选框,它接受真/假。“false"将取消检查,“true"将设置检查。

用法:

选择 <text|query> true|false

例子:

选择 "C:.Checkbox&&T:Milk"

进度

进度用于在滑块上设置一个值,例如“.SeekBar"的类名。它在 FindNode (getNodes(RI)) 中显示为"rangeInfo”,它具有整数或浮点数类型,具有最小值和最大值。确保该值在范围内。

用法:

进度 <query> <value in integer or float>

例子:

进度 "T:Notifications&&OY:1&&OX:1", 1200

get

从 FindNode 获取信息。它有4种get(需要时会增加),参数是可选的。返回值将保存到日志文件并从 JavaScript"getOutput()”获取。

用法:

get <query>, <type>

类型:

  • “id”:获取查询的id/ids。没有争论。
  • "text":获取查询匹配节点的文本信息。没有争论。
  • "description":获取查询匹配节点的描述信息。没有争论。
  • "node": 根据可选参数获取匹配节点的信息。

例子:

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 {<query or action>}
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 和 JS 之间传递数据:

  • 可以在 JavaScript 函数 getOutput() 中检索 AAIS"get"和"sendAai"输出。
  • 所有 AAIS 双引号都可以在模板文字中包含表达式“…${<expression>}…”,这允许将变量从 JS 传递到 AAIS。

例如

{ <JavaScript> code }

或者

{
    <JavaScript code>
}

例子:

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() → 设备

将返回当前设备。

getDevices() → 设备数组

将返回所有选定的设备。

saveVar(<名称>, <值>)

将存储指定名称的变量,该变量存储在 getDevice() 的范围内。

loadVar(<名称>) → <值>

将加载具有指定名称的变量并返回值。该值仅在使用相同的 getDevice() 由 saveVar() 存储时可见。

saveGlobalVar(<名称>, <值>)

将存储在由名称标识的全局范围内,任何设备都可以访问它。

loadGlobalVar(<名称>) → <值>

将返回由名称标识的全局范围。

doOnce() → 真|假

将在第一次运行时返回 true,后续运行将返回 false。

getOutput() → 从 FindNode 输出

此函数仅对"get"和"sendAai"有效,JavaScript 代码块需要紧跟在"get"或"sendAai"命令之后,“getOutput"在其他命令上会产生错误并停止脚本执行。返回格式见日志文件中的内容。

getArg() → 字符串数组

Runner 允许用户将参数作为字符串数组传递给 JavaScript。这与变量替换一起可以在运行时创建查询/操作。当支持命令行模式时,getArg() 将返回命令模式下的参数。Runner 中有一个按钮可以设置参数。

日志(<消息>)

此功能类似于 AAIS 的"打印"功能,它将消息附加到现有 Runner 的日志文件中。

抛出(<消息>)

由于 AAIS 被翻译成 JavaScript,您可以使用 throw(<message>) 来停止执行。错误消息将被记录并显示给用户。

“……${<表达式>}……”

模板文字中的表达式允许任何双引号包含由 ${...} 括起来的 JavaScript 表达式。对于变量替换或简单的 JavaScript 表达式很有用。

AAIS 示例:

此示例打开 Tesla 应用程序并检索汽车的 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 向 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,或者您可以使用 Record 和 Replay 将脚本记录在 AAIS(您需要选择对象模式)文件中。

运行脚本

在Runner中运行AAIS脚本,结果会保存在"Task"中:

  • MDCC:
    • 打开 MDCC 窗口。
    • 通过缩略图设备选择设备或选择一个组。将始终选择主设备。
    • 点击"执行器”。
    • 选择一个或多个脚本,当复选框被点击时,它会显示执行顺序。
    • 单击运行按钮,它将在设备上运行脚本。错误将显示在 Runner 旁边的消息框中。单击"日志"以访问日志。
  • 波分复用器:
    • 在 WDM 设备窗口中,单击菜单"执行器”。
    • 选择一个或多个脚本,当复选框被点击时,它会显示执行顺序。
    • 单击运行按钮,它将在设备上运行脚本。
    • 单击"Runner first"按钮上的任务窗口。
    • 任务窗口将出现,可以查看进度和生成的日志文件。