From cf82cd280278e07a910a71de1d528f150b318ba6 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Wed, 25 Oct 2017 13:23:46 +0800 Subject: [PATCH] add: search for scripts and posts --- app/build.gradle | 21 +- app/src/main/assets/docs/all.html | 2633 +++++++++++++++++ app/src/main/assets/docs/app.html | 165 ++ app/src/main/assets/docs/assets/dnt_helper.js | 49 + app/src/main/assets/docs/assets/sh.css | 25 + .../assets/docs/assets/sh_javascript.min.js | 1 + app/src/main/assets/docs/assets/sh_main.js | 553 ++++ app/src/main/assets/docs/assets/style.css | 523 ++++ app/src/main/assets/docs/console.html | 173 ++ .../docs/coordinates-based-automation.html | 267 ++ app/src/main/assets/docs/documentation.html | 139 + app/src/main/assets/docs/engines.html | 196 ++ app/src/main/assets/docs/events.html | 499 ++++ app/src/main/assets/docs/files.html | 297 ++ app/src/main/assets/docs/globals.html | 211 ++ app/src/main/assets/docs/images.html | 256 ++ app/src/main/assets/docs/index.html | 109 + app/src/main/assets/docs/keys.html | 263 ++ app/src/main/assets/docs/modules.html | 109 + app/src/main/assets/docs/overview.html | 79 + app/src/main/assets/docs/qa.html | 79 + app/src/main/assets/docs/shell.html | 459 +++ app/src/main/assets/docs/timers.html | 133 + app/src/main/assets/docs/ui.html | 79 + app/src/main/assets/docs/util.html | 1212 ++++++++ .../assets/docs/widgets-based-automation.html | 727 +++++ app/src/main/assets/docs/work-with-java.html | 79 + .../ui/doc/OnlineDocsFragment.java | 13 +- .../scriptdroid/ui/main/MainActivity.java | 31 +- .../scriptdroid/ui/main/QueryEvent.java | 20 + .../ui/main/ViewPagerFragment.java | 16 +- .../ui/main/community/CommunityFragment.java | 41 +- .../ui/main/scripts/MyScriptListFragment.java | 39 +- .../ui/main/scripts/ScriptListView.java | 13 + .../ui/main/task/TaskManagerFragment.java | 12 + .../com/stardust/widget/SearchViewItem.java | 72 + .../res/drawable/ic_search_white_36dp.png | Bin 0 -> 1119 bytes app/src/main/res/menu/menu_main.xml | 13 + app/src/main/res/values/strings.xml | 1 + .../autojs/engine/RhinoJavaScriptEngine.java | 1 + 40 files changed, 9572 insertions(+), 36 deletions(-) create mode 100644 app/src/main/assets/docs/all.html create mode 100644 app/src/main/assets/docs/app.html create mode 100644 app/src/main/assets/docs/assets/dnt_helper.js create mode 100644 app/src/main/assets/docs/assets/sh.css create mode 100644 app/src/main/assets/docs/assets/sh_javascript.min.js create mode 100644 app/src/main/assets/docs/assets/sh_main.js create mode 100644 app/src/main/assets/docs/assets/style.css create mode 100644 app/src/main/assets/docs/console.html create mode 100644 app/src/main/assets/docs/coordinates-based-automation.html create mode 100644 app/src/main/assets/docs/documentation.html create mode 100644 app/src/main/assets/docs/engines.html create mode 100644 app/src/main/assets/docs/events.html create mode 100644 app/src/main/assets/docs/files.html create mode 100644 app/src/main/assets/docs/globals.html create mode 100644 app/src/main/assets/docs/images.html create mode 100644 app/src/main/assets/docs/index.html create mode 100644 app/src/main/assets/docs/keys.html create mode 100644 app/src/main/assets/docs/modules.html create mode 100644 app/src/main/assets/docs/overview.html create mode 100644 app/src/main/assets/docs/qa.html create mode 100644 app/src/main/assets/docs/shell.html create mode 100644 app/src/main/assets/docs/timers.html create mode 100644 app/src/main/assets/docs/ui.html create mode 100644 app/src/main/assets/docs/util.html create mode 100644 app/src/main/assets/docs/widgets-based-automation.html create mode 100644 app/src/main/assets/docs/work-with-java.html create mode 100644 app/src/main/java/com/stardust/scriptdroid/ui/main/QueryEvent.java create mode 100644 app/src/main/java/com/stardust/widget/SearchViewItem.java create mode 100644 app/src/main/res/drawable/ic_search_white_36dp.png create mode 100644 app/src/main/res/menu/menu_main.xml diff --git a/app/build.gradle b/app/build.gradle index 35dee1c3..3dd718b8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.stardust.scriptdroid" minSdkVersion 17 targetSdkVersion 23 - versionCode 211 - versionName "3.0.0 Alpha12" + versionCode 212 + versionName "3.0.0 Alpha13" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true ndk { @@ -35,9 +35,6 @@ android { targetCompatibility JavaVersion.VERSION_1_8 encoding = 'utf-8' } - dataBinding { - enabled = true - } lintOptions { disable 'MissingTranslation' disable 'ExtraTranslation' @@ -49,20 +46,6 @@ android { } } - dexcount { - format = "list" - includeClasses = true - includeFieldCount = true - includeTotalMethodCount = true - orderByMethodCount = true - verbose = true - maxTreeDepth = Integer.MAX_VALUE - teamCityIntegration = false - enableForInstantRun = false - teamCitySlug = null - runOnEachAssemble = true - maxMethodCount = 128000 - } configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1' } diff --git a/app/src/main/assets/docs/all.html b/app/src/main/assets/docs/all.html new file mode 100644 index 00000000..f01e96e2 --- /dev/null +++ b/app/src/main/assets/docs/all.html @@ -0,0 +1,2633 @@ + + + + + 全局变量与函数 | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ +
+

目录

+ + +
+ +
+ + + + + +

全局变量与函数#

+

全局变量和函数在所有模块中均可使用。 但以下变量的作用域只在模块内,详见 module文档:

+
    +
  • exports
  • +
  • module
  • +
  • require() +以下的对象是特定于 Auto.js 的。 有些内置对象是 JavaScript 语言本身的一部分,它们也是全局的。
  • +
+

一些模块中的函数为了使用方便也可以直接全局使用,这些函数在此不再赘述。例如timers模块的setInterval等函数。

+

sleep([n])#

+
+

暂停运行n毫秒的时间。1秒等于1000毫秒。

+

launchPackage(packageName)#

+
+

运行包名为packageName的应用主界面(Launcher)。例如,打开微信为:

+
launchPackage("com.tencent.mm");
+

如果存在多个应用包名相同的情况(如双开应用),如何处理取决于操作系统。在MIUI中会弹出多开应用的选择界面。

+

launchApp(appName)#

+
+

运行应用名称为appName的应用主界面。当有应用名称相同时只运行其中某一个。
例如,打开微信为:

+
launchApp("微信");
+

currentPackage()#

+

返回最近一次监测到的正在运行的应用的包名,一般可以认为就是当前正在运行的应用的包名。

+

currentActivity()#

+

返回最近一次监测到的正在运行的Activity的名称,一般可以认为就是当前正在运行的Activity的名称。

+

getPackageName(appName)#

+
+

获取应用的包名。例如getPackageName("QQ")为"com.tencent.mobileqq"。如果有相同名称的应用,只返回其中某一个的包名。如果不存在这个名称的应用,会返回null。

+

getAppName(packageName)#

+
+

返回对应包名的应用的名称。如果应用不存在,返回null。

+

openAppSetting(packageName)#

+
+

打开某个应用的应用详情页,也就是管理应用权限和可以停止其运行的页面。如果应用包名不存在,则返回false;否则返回true。

+

setClip(text)#

+
+

设置剪贴板内容。此剪贴板即系统剪贴板,在一般应用的输入框中"粘贴"既可使用。

+

getClip()#

+

返回系统剪贴板的内容。

+

toast(message)#

+
    +
  • message <string>> | <{Object> 要显示的信息
  • +
+

以气泡显示信息message几秒。(具体时间取决于安卓系统,一般都是2秒)

+

注意,信息的显示是"异步"执行的(不属于Looper循环),并且,不会等待信息消失程序才继续执行。如果在循环中执行该命令,可能出现脚本停止运行后仍然有不断的气泡信息出现的情况。 +例如:

+
for(var i = 0; i < 100; i++){
+  toast(i);
+}
+

运行这段程序以后,会很快执行完成,且不断弹出消息,在任务管理中关闭所有脚本也无法停止。 +要保证气泡消息才继续执行可以用:

+
for(var i = 0; i < 100; i++){
+  toast(i);
+  sleep(2000);
+}
+

或者修改toast函数:

+
var _toast_ = toast;
+toast = function(message){
+  _toast_(message);
+  sleep(2000);
+}
+for(var i = 0; i < 100; i++){
+  toast(i);
+  sleep(2000);
+}
+

toastLog(message)#

+
    +
  • message \ | \ 要显示的信息
  • +
+

相当于toast(message);log(message)。显示信息message并在控制台中输出。参见console.log。

+

waitForActivity(activity[, period = 200])#

+
    +
  • activity Activity名称
  • +
  • period 轮询等待间隔(毫秒)
  • +
+

等待指定的Activity出现,period为检查Activity的间隔。

+

waitForPackage(package[, period = 200])#

+
    +
  • package 包名
  • +
  • period 轮询等待间隔(毫秒)
  • +
+

等待指定的应用出现。例如waitForPackage("com.tencent.mm")为等待当前界面为微信。

+

exit()#

+

立即停止脚本运行。

+

random(min, max)#

+
    +
  • min <number> 随机数产生的区间下界
  • +
  • max <number> 随机数产生的区间上界
  • +
+

返回一个在[min...max]之间的随机数。例如random(0, 2)可能产生0, 1, 2.

+

random()#

+

返回在[0, 1)的随机浮点数。

+

context#

+

全局变量。一个android.content.Context对象。

+

注意该对象为ApplicationContext,因此不能用于界面、对话框等的创建。 +

+ +

SimpleActionAutomator#

+
Stability: 2 - Stable

SimpleActionAutomator提供了一些模拟简单操作的函数,例如点击文字、模拟按键等。这些函数可以直接作为全局函数使用。

+

click(text[, i])#

+
    +
  • text <string> 要点击的文本
  • +
  • i <number> 如果相同的文本在屏幕中出现多次,则i表示要点击第几个文本, i从0开始计算
  • +
+

返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。

+

该函数可以点击大部分包含文字的按钮。例如微信主界面下方的"微信", "联系人", "发现", "我"的按钮。
通常与while同时使用以便点击按钮直至成功。例如:

+
while(!click("扫一扫"));
+

当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部点击成功。

+

i是从0开始计算的, 也就是, click("啦啦啦", 0)表示点击屏幕上第一个"啦啦啦", click("啦啦啦", 1)表示点击屏幕上第二个"啦啦啦"。

+
+

文本所在区域指的是,从文本处向其父视图寻找,直至发现一个可点击的部件为止。

+
+

click(left, top, bottom, right)#

+
    +
  • left <number> 要点击的长方形区域左边与屏幕左边的像素距离
  • +
  • top <number> 要点击的长方形区域上边与屏幕上边的像素距离
  • +
  • bottom <number> 要点击的长方形区域下边与屏幕下边的像素距离
  • +
  • right <number> 要点击的长方形区域右边与屏幕右边的像素距离
  • +
+

注意,该函数一般只用于录制的脚本中使用,在自己写的代码中使用该函数一般不要使用该函数。

+

点击在指定区域的控件。当屏幕中并未包含与该区域严格匹配的区域,或者该区域不能点击时返回false,否则返回true。

+

有些按钮或者部件是图标而不是文字(例如发送朋友圈的照相机图标以及QQ下方的消息、联系人、动态图标),这时不能通过click(text, i)来点击,可以通过描述图标所在的区域来点击。left, bottom, top, right描述的就是点击的区域。

+

至于要定位点击的区域,可以在悬浮窗使用布局分析工具查看控件的bounds属性。

+

通过无障碍服务录制脚本会生成该语句。

+

longClick(text[, i]))#

+
    +
  • text <string> 要长按的文本
  • +
  • i <number> 如果相同的文本在屏幕中出现多次,则i表示要长按第几个文本, i从0开始计算
  • +
+

返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。

+

当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部长按成功。

+

scrollUp([i])#

+
+

找到第i+1个可滑动控件上滑或左滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。

+

另外不加参数时scrollUp()会寻找面积最大的可滑动的控件上滑或左滑,例如微信消息列表等。

+

参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)为滑动第一个可滑动控件。

+

scrollDown([i])#

+
+

找到第i+1个可滑动控件下滑或右滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。

+

另外不加参数时scrollUp()会寻找面积最大的可滑动的控件下滑或右滑。

+

参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)为滑动第一个可滑动控件。

+

setText([i, ]text)#

+
    +
  • i <number> 表示要输入的为第i + 1个输入框
  • +
  • text <string> 要输入的文本
  • +
+

返回是否输入成功。当找不到对应的文本框时返回false。

+

不加参数i则会把所有输入框的文本都置为text。例如setText("测试")

+

这里的输入文本的意思是,把输入框的文本置为text,而不是在原来的文本上追加。

+

input([i, ]text)#

+
    +
  • i <number> 表示要输入的为第i + 1个输入框
  • +
  • text <string> 要输入的文本
  • +
+

返回是否输入成功。当找不到对应的文本框时返回false。

+

不加参数i则会把所有输入框的文本追加内容text。例如input("测试")

+

UiSelector#

+

选择器(UiSelector)是稍微复杂的自动操作脚本所必须。使用选择器的一般步骤是:

+
    +
  1. 用各种筛选条件找出想要的控件,如某个文本控件、列表控件、图片控件
  2. +
  3. 对找出的控件执行想要的操作,如点击、滑动、设置文字、长按
  4. +
+

问题的关键在于如何找出想要的控件。对于文本控件一般通过他的文字来定位他,图片控件则通过id或者图片描述(desc)。选择器所做的就是提供这些筛选条件并给出筛选结果。

+

选择器提供了更强大的定位界面控件与对其进行操作的功能,可以用他们完成更多的自动操作和提取界面信息。
选择器通过附加筛选条件,筛选出符合条件的控件或控件集合,之后可以对这些控件这些操作。
可供选择的筛选条件包括:

+
    +
  • id
  • +
  • text 文本
  • +
  • desc 描述(Content-Description)
  • +
  • className 类名
  • +
  • packageName 包名
  • +
  • bounds 在屏幕上的范围
  • +
  • drawingOrder 绘制顺序
  • +
  • 各种属性,主要包括:
      +
    • clickable 可点击
    • +
    • longClickable 可长按
    • +
    • checkable 可勾选
    • +
    • checked 被勾选
    • +
    • scrollable 可滑动
    • +
    • selected 被选择
    • +
    • editable 可编辑
    • +
    • visibleToUser 可见
    • +
    • enabled 已启用
    • +
    +
  • +
+

要对选择器所确定的筛选条件,对屏幕上的控件进行筛选,调用方法find(), findOne(), untilFind()。其中find(), untilFind()返回控件的集合,findOne()返回一个控件。untilFind和findOne函数会一直寻找直到屏幕上出现满足条件的控件为止。
一个完整的选择器示例如下:

+
var emoj = id("name").packageName("com.tencent.mobileqq").clickable()
+        .className("ImageView").drawingOrder(5).findOne();
+emoj.click();
+

上述代码是找到QQ聊天界面下面的表情按钮(第5个按钮)并点击。也可以简化为:

+
id("name").packageName("com.tencent.mobileqq").clickable()
+       .className("ImageView").click();
+

这段代码意思是,找出id为"name", 包名为"com.tentcent.mobileqq",类名为ImageView的所有可点击控件,对他们执行点击动作。

+

最后的click()函数相当于untilFind().click()。也就是如果只需要在找到控件以后立即进行操作,只需要调用相应的操作函数,而不需要先调用find等函数等到控件再操作。
要获取屏幕上的控件的信息(例如id, text, desc, bounds等),可以开启悬浮窗,使用界面层次查看和界面范围查看。

+

选择器部分内容如果有安卓开发经验会更容易掌握。

+

id(resId)#

+
    +
  • resId <string> 控件的id,以"包名:id/"开头,例如"com.tencent.mm:id/send_btn"。也可以不指定包名,这时会以当前正在运行的应用的包名来补全id。例如id("send_btn"),在QQ界面想当于id("com.tencent.mobileqq:id/send_btn")。
  • +
+

附加id严格匹配筛选条件。

+

控件的id属性通常是可以用来确定控件的唯一标识,如果一个控件有id,那么使用id来找到他是最好的方法。要查看屏幕上的控件的id,可以开启悬浮窗并使用界面工具,点击相应控件即可查看。若查看到的控件id为null, 表示该控件没有id。另外,在列表中会出现多个控件的id相同的情况。例如微信的联系人列表,每个头像的id都是一样的。此时不能用id来唯一确定控件。

+

在QQ界面经常会出现多个id为"name"的控件,在微信上则每个版本的id都会变化。对于这些软件而言比较难用id定位控件。

+

idContains(str)#

+
    +
  • str <string> id要包含的字符串
  • +
+

附加控件id包含字符串str的筛选条件。

+

idStartsWith(prefix)#

+
+

附加id需要以prefix开头的筛选条件。

+

idEndsWith(suffix)#

+
+

附加id需要以suffix结束的筛选条件。

+

idMatches(String)#

+
    +
  • String <string> id要满足的正则表达式
  • +
+

附加id需要满足正则表达式。有关正则表达式,可以查看菜鸟教程

+

这里的正则表达式是Java的正则表达式,不能直接使用JavaScript的正则表达式。

+
idMatches("[a-zA-Z]+")
+

text(str)#

+
+

附加控件文本等于字符串str的筛选条件。

+

控件的text(文本)属性是控件上的显示的文字,例如微信左上角的"微信"文本。对于图片或者其他控件通常text属性为null。

+

textContains(str)#

+
+

附加控件文本需要以prefix开头的筛选条件。

+

textStartsWith(prefix)#

+
+

附加控件文本需要以prefix开头的筛选条件。

+

textEndsWith(suffix)#

+
+

附加控件文本需要以suffix结束的筛选条件。

+

textMatches(str)#

+
    +
  • String <string> 要满足的正则表达式
  • +
+

附加控件文本需要满足正则表达式的条件。

+

desc(str)#

+
+

附加控件描述等于字符串str的筛选条件。

+

控件的desc(描述,全称为Content-Description)属性是对一个控件的描述,例如网易云音乐右上角的放大镜图标的描述为搜索。要查看一个控件的描述,同样地可以借助悬浮窗查看。

+

desc属性同样是定位控件的利器。

+

descContains(str)#

+
+

附加控件描述需要以prefix开头的筛选条件。

+

descStartsWith(prefix)#

+
+

附加控件描述需要以prefix开头的筛选条件。

+

descEndsWith(suffix)#

+
+

附加控件描述需要以suffix结束的筛选条件。

+

descMatches(str)#

+
    +
  • String <string> 要满足的正则表达式
  • +
+

附加控件描述需要满足正则表达式的条件。

+

className(str)#

+
+

附加控件类名等于字符串str的筛选条件。

+

控件的className属性是一个控件的具体类型,例如图片控件通常为ImageView,文本控件通常为TextView, 输入框通常为EditText。(若一个控件是在android.widget包里的,那么android.widget可以省略。但除此之外的其他控件必须是类的全名,例如"com.stardust.theme.ThemeColorImageView")。

+

classNameContains(str)#

+
+

附加控件类名需要以prefix开头的筛选条件。

+

classNameStartsWith(prefix)#

+
+

附加控件类名需要以prefix开头的筛选条件。

+

classNameEndsWith(suffix)#

+
+

附加控件类名需要以suffix结束的筛选条件。

+

classNameMatches(str)#

+
    +
  • String <string> 要满足的正则表达式
  • +
+

附加控件类名需要满足正则表达式的条件。

+

packageName(str)#

+
+

附加包名等于字符串str的筛选条件。

+

packageName属性也即控件所属的应用的包名(参见《shell命令:应用包名》),通常用来保证当前运行的应用是想要的应用。

+

packageNameContains(str)#

+
+

附加包名需要以prefix开头的筛选条件。

+

packageNameStartsWith(prefix)#

+
+

附加包名需要以prefix开头的筛选条件。

+

packageNameEndsWith(suffix)#

+
+

附加包名需要以suffix结束的筛选条件。

+

packageNameMatches(str)#

+
    +
  • String <string> 要满足的正则表达式
  • +
+

附加包名需要满足正则表达式的条件。

+

bounds(l, t, r, b)#

+
    +
  • l, t, r, b 用来定位控件在屏幕上的范围的四个整数
  • +
+

boundsInside(l, t, r, b)#

+

boundsContains(l, t, r, b)#

+

drawingOrder(order)#

+
    +
  • order <number> 控件在父视图中的绘制顺序,在一些
  • +
+

checkable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可勾选, 默认为true
  • +
+

附加控件是否可勾选的条件。可勾选指的是,例如QQ和微信发送图片时图片的勾选。

+

selected([b = true])#

+
    +
  • b <Boolean> 表示控件是否被选中,默认为true
  • +
+

附加控件是否被选中的条件。被选中指的是,例如QQ聊天界面点击下方的表情按钮时,会出现自己收藏的表情,这时表情按钮便处于选中状态。

+

clickable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可点击, 默认为true
  • +
+

附加控件是否可点击的条件。但并非所有clickable为false的控件都真的不能点击,这取决于控件的实现。因而要确定一个控件的clickable属性,可以开启悬浮窗工具。

+

longClickable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可长按, 默认为true
  • +
+

附加控件是否可长按的条件。

+

enabled([b = true])#

+
    +
  • b <Boolean> 表示控件是否已启用, 默认为true
  • +
+

附加控件是否已启用的条件。大多数控件都是启用的状态,处于“禁用”状态通常是灰色并且不可点击。

+

scrollable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可滑动, 默认为true
  • +
+

附加控件是否可滑动的条件。

+

editable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可编辑, 默认为true
  • +
+

附加控件是否可编辑的条件。一般来说可编辑的控件为输入框(EditText)。

+

contentInvalid([b = true])#

+
    +
  • b <Boolean> 表示控件是否是contentInvalid, 默认为true
  • +
+

我也不知道是什么,下次再补充吧。

+

contextClickable([b = true])#

+
    +
  • b <Boolean> 表示控件是否是contextClickable, 默认为true
  • +
+

我也不知道是什么,下次再补充吧。

+

multiLine([b = true])#

+
    +
  • b <Boolean> 表示文本或输入框控件是否是多行显示的, 默认为true
  • +
+

附加控件是否文本或输入框控件是否是多行显示的条件。

+

findOne()#

+

根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到屏幕上出现满足条件的一个控件为止,并返回该控件。如果找不到控件,当屏幕内容发生变化时会重新寻找,直至找到。参见控件

+

find()#

+

根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,找到所有满足条件的控件集合并返回。这个搜索只进行一次,并不保证一直会找到,因而会出现返回的控件集合为空的情况。参见控件集合

+

可以通过empty()或nonEmpty()函数判断找到的是否为空。例如:

+
var c = className("AbsListView").find();
+if(c.empty()){
+    toast("找到啦");
+}else{
+    toast("没找到╭(╯^╰)╮");
+}
+

untilFind()#

+

根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到找到至少一个满足条件的控件为止,并返回所有满足条件的控件集合。参见控件集合

+

exists()#

+

判断屏幕上是否存在控件符合选择器所确定的条件。例如要判断某个文本出现就执行某个动作,可以用:

+
if(text("嘿嘿嘿").exists()){
+    //嘿嘿嘿
+}
+

waitFor()#

+

等待屏幕上出现符合条件的控件。

+
text("嘿嘿嘿").waitFor();
+

click()#

+

找到所有符合条件的控件并点击。相当于untilFind().click()。参见click)。

+

longClick()#

+

找到所有符合条件的控件并长按。相当于untilFind().longClick()。参见longClick)。

+

copy()#

+

找到所有符合条件的控件并复制其内容,只对文本框或输入框控件有文字选中时有效。相当于untilFind().copy()。参见copy)。

+

paste()#

+

找到所有符合条件的控件并粘贴,只对输入框控件有效。相当于untilFind().paste()。参见paste)。

+

select()#

+

找到所有符合条件的控件并选中。相当于untilFind().select()。参见select)。

+

cut()#

+

找到所有符合条件的控件并剪切其内容,只对文本框或输入框控件有文字选中时有效。相当于untilFind().cut()。参见cut)。

+

collapse()#

+

找到所有符合条件的控件并折叠。相当于untilFind().collapse()。参见collapse)。

+

expand()#

+

找到所有符合条件的控件并展开。相当于untilFind().expand()。参见expand)。

+

show()#

+

找到所有符合条件的控件并使其出现在屏幕上。相当于untilFind().show()。参见show)。

+

scrollForward()#

+

找到所有符合条件的控件并向前滑。相当于untilFind().scrollForward()。参见scrollForward)。
向前滑指的是,对于左右滑动的控件向右滑,上下滑动的控件向下滑。

+

scrollBackward()#

+

找到所有符合条件的控件并向后滑。相当于untilFind().scrollBackward()。参见scrollBackward)。
向后滑指的是,对于左右滑动的控件向左滑,上下滑动的控件向上滑。

+

scrollUp()#

+

找到所有符合条件的控件并向上滑。相当于untilFind().scrollUp()。参见scrollUp)。

+

scrollDown()#

+

找到所有符合条件的控件并向下滑。相当于untilFind().scrollDown()。参见scrollDown)。

+

scrollLeft()#

+

找到所有符合条件的控件并向左滑。相当于untilFind().scrollLeft()。参见scrollLeft)。

+

scrollRight()#

+

找到所有符合条件的控件并向右滑。相当于untilFind().scrollRight()。参见scrollRight)。

+

contextClick()#

+

文档缺失

+

setSelection(start, end)#

+
    +
  • start <number> 文字选中开始位置
  • +
  • end <number> 文字选中结束位置
  • +
+

找到所有符合条件的控件并设置文字选中区域,只对文本控件和输入框有效。相当于untilFind().setSelection()。参见setSelection

+

setText(text)#

+
    +
  • text <string> 要设置的文本 +找到所有符合条件的控件并设置文字,只对输入框有效。相当于untilFind().setText()。参见setText
  • +
+

UiCollection#

+

UiCollection, 控件集合, 通过选择器的find(), untilFind()方法返回的对象。可以对其进行操作或者获取其信息。

+

UiCollection.size()#

+

返回集合中的控件数。

+

UiCollection.get(i)#

+
+

返回集合中第i+1个控件(UiObject)。

+

UiCollection.each(func)#

+
    +
  • func \ 遍历函数
  • +
+

遍历集合。例如:

+
var c = clickable();
+c.each(function(o){
+    log(o.text());
+});
+

empty()#

+

返回控件集合是否为空。

+

nonEmpty()#

+

返回控件集合是否非空。

+

UiCollection.filter(filter)#

+
    +
  • filter \ 过滤函数。参数为UiObject,返回值为Boolean。
  • +
+

过滤出控件集合中符合条件的子控件。例如要过滤出所有子控件数目为1的控件为:

+
var newCollection = collection.filter(function(obj){
+    return obj.childCount() == 1;
+});
+

UiCollection.find(selector)#

+
    +
  • selector \ 选择器
  • +
+

根据selector所确定的条件在该控件集合的控件和子控件找到所有符合条件的控件并返回控件集合。

+

注意这会递归地遍历控件集合里所有的控件以及他们的子控件。和filter函数不同。

+

例如:

+
var names = id("name");
+var clickableNames = names.find(clickable());
+

UiCollection.findOne(selector)#

+
    +
  • selector \ 选择器
  • +
+

根据selector所确定的条件在该控件集合中找到一个符合条件的控件并返回控件。若找不到则返回null。

+

UiCollection.click()#

+

点击集合中所有控件,并返回是否全部点击成功。

+

UiCollection.longClick()#

+

长按集合中所有控件,并返回是否全部操作成功。

+

UiCollection.copy()#

+

对集合中所有控件执行复制操作,并返回是否全部操作成功。

+

UiCollection.paste()#

+

对集合中所有控件执行粘贴操作,并返回是否全部操作成功。

+

UiCollection.select()#

+

对集合中所有控件执行选中操作,并返回是否全部操作成功。

+

UiCollection.cut()#

+

对集合中所有控件执行剪切操作,并返回是否全部操作成功。

+

UiCollection.collapse()#

+

对集合中所有控件执行折叠操作,并返回是否全部操作成功。

+

UiCollection.expand()#

+

对集合中所有控件执行展开操作,并返回是否全部操作成功。

+

UiCollection.show()#

+

对集合中所有控件执行显示操作,并返回是否全部操作成功。

+

UiCollection.scrollForward()#

+

对集合中所有控件执行向前滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollBackward()#

+

对集合中所有控件执行向后滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollUp()#

+

对集合中所有控件执行向上滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollDown()#

+

对集合中所有控件执行向下滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollLeft()#

+

对集合中所有控件执行向左滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollRight()#

+

对集合中所有控件执行向右滑的操作,并返回是否全部操作成功。

+

UiCollection.contextClick()#

+

UiCollection.setSelection(start, end)#

+
    +
  • start <number> 文字选中开始位置
  • +
  • end <number> 文字选中结束位置
  • +
+

对集合中所有控件设置文字选中区域,并返回是否全部操作成功。

+

UiCollection.setText(text)#

+
    +
  • text <string> 要设置的文本 +对集合中所有控件设置文本,并返回是否全部操作成功。
  • +
+

UiObject#

+

控件, 选择器的findOne方法返回的对象。和UiCollection有相似的方法,不再赘述。除此之外还有以下方法。

+

child(i)#

+
+

返回第i+1个子控件(UiObject)。

+

parent()#

+

返回父控件(UiObject)。

+

children()#

+

返回该控件的所有子控件组成的控件集合。

+

childCount()#

+

返回子控件数目。

+

bounds()#

+

返回控件在屏幕上的范围,其值是一个[Rect]对象。

+

boundsInParent()#

+

返回控件在父控件中的范围,其值是一个[Rect]对象。

+

drawingOrder()#

+

返回控件的绘制次序。

+

id()#

+

返回控件的id,可能为null。

+

text()#

+

返回控件的文本,如果控件没有文本,返回""。

+

findByText(text)#

+
+

根据文本text在子控件中递归地寻找并返回文本或描述(desc)包含这段文本text的控件,返回它们组成的集合。。

+

find(selector)#

+
    +
  • selector \ 选择器
  • +
+

根据选择器selector在子控件中递归地寻找符合条件的控件,返回它们组成的集合。

+

findOne#

+

find(selector)#

+
    +
  • selector \ 选择器
  • +
+

根据选择器selector在子控件中递归地寻找一个符合条件的控件。找不到则返回null。

+

Rect#

+

UiObject.bounds(), UiObject.boundsInParent()返回的对象。表示一个长方形。

+

Rect.left#

+

长方形左边界的x坐标、

+

Rect.right#

+

长方形左边界的x坐标、

+

Rect.top#

+

长方形上边界的y坐标、

+

Rect.bottom#

+

长方形下边界的y坐标、

+

Rect.centerX()#

+

长方形中点x坐标。

+

Rect.centerY()#

+

长方形中点y坐标。

+

Rect.width()#

+

长方形宽度。通常可以作为控件宽度。

+

Rect.height()#

+

长方形高度。通常可以作为控件高度。

+

Rect.contains(r)#

+
    +
  • r \
  • +
+

返回是否包含另一个长方形r。

+

Rect.intersect(r)#

+
    +
  • r \
  • +
+

返回是否和另一个长方形相交。

+ + +

Android7.0以上点按与手势模拟#

+
Stability: 2 - Stable

本章节介绍了一些适用于Android7.0以上、不需要root权限、依赖于无障碍服务的点按与手势模拟的全局函数。

+

注意以下命令只有Android7.0及以上才有效

+

click(x, y)#

+
+

模拟点击坐标(x, y),并返回是否点击成功。只有在点击执行完成后脚本才继续执行。

+

一般而言,只有点击过程(大约150毫秒)中被其他事件中断(例如用户自行点击)才会点击失败。

+

使用该函数模拟连续点击时可能有点击速度过慢的问题,这时可以用[press][]函数代替。

+
+

可以在开发者选项中启用指针位置来查看坐标

+
+

longClick(x, y)#

+
+

模拟长按坐标(x, y), 并 返回是否成功。只有在长按执行完成(大约600毫秒)时脚本才会继续执行。

+

一般而言,只有长按过程中被其他事件中断(例如用户自行点击)才会长按失败。

+

press(x, y, duration)#

+
    +
  • x <number> 要按住的坐标的x值
  • +
  • y <number> 要按住的坐标的y值
  • +
  • duration <number> 按住时长,单位毫秒
  • +
+

模拟按住坐标(x, y), 并返回是否成功。只有按住操作执行完成时脚本才会继续执行。

+

如果按住时间过短,那么会被系统认为是点击;如果时长超过500毫秒,则认为是长按。

+

一般而言,只有按住过程中被其他事件中断才会操作失败。

+

swipe(x1, y1, x2, y2, duration)#

+
    +
  • x1 <number> 滑动的起始坐标的x值
  • +
  • y1 <number> 滑动的起始坐标的y值
  • +
  • x2 <number> 滑动的结束坐标的x值
  • +
  • y2 <number> 滑动的结束坐标的y值
  • +
  • duration <number> 滑动时长,单位毫秒
  • +
+

模拟从坐标(x1, y1)滑动到坐标(x2, y2),并返回是否成功。只有滑动操作执行完成时脚本才会继续执行。

+

一般而言,只有滑动过程中被其他事件中断才会滑动失败。

+

gesture(duration, [x1, y1], [x2, y2], ...)#

+
    +
  • duration <number> 手势的时长
  • +
  • [x, y] ... 手势滑动路径的一系列坐标
  • +
+

模拟手势操作。例如gesture(1000, [0, 0], [500, 500], [500, 1000])为模拟一个从(0, 0)到(500, 500)到(500, 100)的手势操作,时长为2秒。

+

gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)#

+

同时模拟多个手势。每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势;duration为手势执行时长;坐标为手势经过的点的坐标。其中delay参数可以省略,默认为0。

+

例如手指捏合:

+
gestures([0, 500, [800, 300], [500, 1000]],
+         [0, 500, [300, 1500], [500, 1000]]);
+

setScreenMetrics(width, height)#

+
    +
  • width <number> 屏幕宽度,单位像素
  • +
  • height <number> 屏幕高度,单位像素
  • +
+

设置脚本坐标点击所适合的屏幕宽高。如果脚本运行时,屏幕宽度不一致会自动放缩坐标。

+

例如在1920*1080的设备中,某个操作的代码为

+
setScreenMetrics(1080, 1920);
+click(800, 200);
+longClick(300, 500);
+

那么在其他设备上AutoJs会自动放缩坐标以便脚本仍然有效。

+

RootAutomator#

+
Stability: 2 - Stable

RootAutomator是一个使用root权限来模拟触摸的对象,用它可以完成触摸与多点触摸,并且这些动作的执行没有延迟。

+

注意以下命令需要root权限

+
var ra = new RootAutomator();
+

RootAutomator.tap(x, y[, id])#

+
    +
  • x <number> 横坐标
  • +
  • y <number> 纵坐标
  • +
  • id <number> 多点触摸id,可选,默认为1,可以通过setDefaultId指定。
  • +
+

点击位置(x, y)。其中id是一个整数值,用于区分多点触摸,不同的id表示不同的"手指",例如:

+
var ra = new RootAutomator();
+//让"手指1"点击位置(100, 100)
+ra.tap(100, 100, 1);
+//让"手指2"点击位置(200, 200);
+ra.tap(200, 200, 2);
+ra.exit();
+

如果不需要多点触摸,则不需要id这个参数。 +多点触摸通常用于手势或游戏操作,例如模拟双指捏合、双指上滑等。

+

RootAutomator.swipe(x1, x2, y1, y2[, duration, id])#

+
    +
  • x1 <number> 滑动起点横坐标
  • +
  • y1 <number> 滑动起点纵坐标
  • +
  • x2 <number> 滑动终点横坐标
  • +
  • y2 <number> 滑动终点纵坐标
  • +
  • duration <number> 滑动时长,单位毫秒,默认值为300
  • +
  • id <number> 多点触摸id,可选,默认为1
  • +
+

模拟一次从(x1, y1)到(x2, y2)的时间为duration毫秒的滑动。

+

RootAutomator.press(x, y, duration[, id])#

+
+

模拟按下位置(x, y),时长为duration毫秒。

+

使用该函数模拟连续点击时可能有点击速度过慢的问题,这时可以用[RootAutomator.press][]函数代替。

+

RootAutomator.longPress(x, y[\, id])#

+
+

模拟长按位置(x, y)。

+

以上为简单模拟触摸操作的函数。如果要模拟一些复杂的手势,需要更底层的函数。

+

RootAutomator.touchDown(x, y[\, id])#

+
+

模拟手指按下位置(x, y)。

+

RootAutomator.touchMove(x, y[\, id])#

+
+

模拟移动手指到位置(x, y)。

+

RootAutomator.touchUp([id])#

+
    +
  • id <number> 多点触摸id,可选,默认为1
  • +
+

模拟手指弹起。

+

使用root权限点击和滑动的简单命令#

+
Stability: 1 - Experimental

注意:本章节的函数在后续版本很可能有改动!请勿过分依赖本章节函数的副作用。推荐使用[RootAutomator][]代替本章节的触摸函数。

+

以下函数均需要root权限,可以实现任意位置的点击、滑动等。

+
    +
  • 这些函数通常首字母大写以表示其特殊的权限。
  • +
  • 这些函数均不返回任何值。
  • +
  • 并且,这些函数的执行是异步的、非阻塞的,在不同机型上所用的时间不同。脚本不会等待动作执行完成才继续执行。因此最好在每个函数之后加上适当的sleep来达到期望的效果。
  • +
+

例如:

+
Tap(100, 100);
+sleep(500);
+

注意,动作的执行可能无法被停止,例如:

+
for(var i = 0; i < 100; i++){
+  Tap(100, 100);
+}
+

这段代码执行后可能会出现在任务管理中停止脚本后点击仍然继续的情况。 +因此,强烈建议在每个动作后加上延时:

+
for(var i = 0; i < 100; i++){
+  Tap(100, 100);
+  sleep(500);
+}
+

Tap(x, y)#

+
+

点击位置(x, y), 您可以通过"开发者选项"开启指针位置来确定点击坐标。

+

Swipe(x1, y1, x2, y2, [duration])#

+
    +
  • x1, y1 <number> 滑动起点的坐标
  • +
  • x2, y2 <number> 滑动终点的坐标
  • +
  • duration <number> 滑动动作所用的时间
  • +
+

滑动。从(x1, y1)位置滑动到(x2, y2)位置。 +

+ +

Images#

+
Stability: 2 - Stable

images模块提供了一些手机设备中常见的图片处理函数,包括截图、读写图片、图片剪裁、找色、找图等。

+

requestScreenCapture([width, height])#

+
+

向系统申请屏幕截图权限,返回是否请求成功。

+

第一次使用该函数会弹出截图权限请求,建议选择“总是允许”。

+

这个函数只是申请截图权限,并不会真正执行截图,真正的截图函数是[captureScreen][]都调用一次。

+

该函数在截图脚本中只需执行一次,而无需每次调用[captureScreen][]都调用一次。

+

不指定参数时默认为屏幕宽高。指定参数时,并不会严格以width和height为截图宽度和高度,而是以和width, height接近的最适合的宽高为截图宽高。例如在1920*1080屏幕中requestScreenCapture(600, 1000)请求的截图的高度一般是540*960。

+

如果在第一次权限请求时选择"总是允许", 之后的脚本执行该函数通常耗时200毫秒以内(测试机型:小米6)。

+

建议在本软件界面运行该函数,在其他软件界面运行时容易出现一闪而过的黑屏。

+

如果要进行截图、找色的软件界面为横屏,则requestScreenCapture函数需要在横屏状态下执行,否则后续截图将会异常,调用findColor等函数时坐标变换会出现错误。

+

captureScreen()#

+

截取当前屏幕并返回一个[Image][]对象。

+

没有截图权限时执行该函数会抛出SecurityException。

+

该函数不会返回null,两次调用可能返回相同的Image对象。这是因为设备截图的更新需要一定的时间,短时间内(几十ms)连续调用则会返回同一张截图。

+

captureScreen(path)#

+
+

截取当前屏幕并以PNG格式保存到path中。如果文件不存在会被创建;文件存在会被覆盖。

+

该函数不会返回任何值。

+

images.pixel(image, x, y)#

+
    +
  • image <Image> 图片
  • +
  • x <number> 要获取的像素的横坐标。
  • +
  • y <y> 要获取的像素的纵坐标。
  • +
+

返回图片image在点(x, y)处的像素的ARGB值。

+

该值的格式为0xAARRGGBB,是一个"32位整数"(虽然JavaScript中并不区分整数类型和其他数值类型。

+

坐标系以图片左上角为原点。以图片左侧边为y轴,上侧边为x轴。

+

images.saveImage(image, path)#

+
    +
  • image <image> 图片
  • +
  • path <string> 路劲
  • +
+

把图片image以PNG格式保存到path中。如果文件不存在会被创建;文件存在会被覆盖。

+

images.findColor(image, color, options)#

+
    +
  • image <image> 图片
  • +
  • color <number> | <string> 要寻找的颜色的RGB值。如果是一个整数,则以0xRRGGBB的形式代表RGB值(A通道会被忽略);如果是字符串,则以"#RRGGBB"代表其RGB值。
  • +
  • options <Object> 选项
  • +
+

在图片中寻找颜色color。找到时返回找到的点[Point][],找不到时返回null。

+

选项包括:

+
    +
  • region <Array> 找色区域。是一个两个或四个元素的数组。(region[0], region[1])表示找色区域的左上角;region[2]*region[3]表示找色区域的宽高。如果只有region只有两个元素,则找色区域为(region[0], region[1])到屏幕右下角。如果不指定region选项,则找色区域为整张图片。
  • +
  • threads <number> 指定找色使用的线程数。不能超过16。最适合的线程数取决于设备。默认线程数为2。
  • +
  • algorithm <string> 指定颜色匹配算法。包括:
      +
    • "equal": 相等匹配,只有与给定颜色color完全相等时才匹配。
    • +
    • "diff": 差值匹配。与给定颜色的R、G、B差的绝对值之和小于threshold时匹配。
    • +
    • "rgb": rgb欧拉距离相似度。与给定颜色color的rgb欧拉距离小于等于threshold时匹配。
    • +
    • "rgb+": 加权rgb欧拉距离匹配(LAB Delta E)。
    • +
    • "hs": hs欧拉距离匹配。hs为HSV空间的色调值。
    • +
    +
  • +
  • threshold <number> 找色时颜色相似度的临界值,范围为0~255(越小越相似,0为颜色相等,255为任何颜色都能匹配)。默认为16。threshold和浮点数相似度(0.0~1.0)的换算为 similarity = (255 - threshold) / 255.
  • +
+

该函数也可以作为全局函数使用。

+

images.findColorInRegion(img, color, x, y[, width, height, threads, algorithm, threshold])#

+

相当于

+
images.findColor(img, color, {
+     region: [x, y, width, height],
+     algorithm: algorithm,
+     threshold: threshold,
+     threads: threads
+});
+

该函数也可以作为全局函数使用。

+

images.findColorEquals(img, color, x, y, width, height, threads)#

+

相当于

+
images.findColor(img, color, {
+   region: [x, y, width, height],
+   algorithm: "equal",
+   threads: threads
+});
+

该函数也可以作为全局函数使用。

+

images.detectsColor(image, color, x, y[, threshold = 16, algorithm = "rgb"])#

+
    +
  • image <Image> 图片
  • +
  • color <number> | <string> 要检测的颜色
  • +
  • x <number> 要检测的位置横坐标
  • +
  • y <number> 要检测的位置纵坐标
  • +
  • threshold <number> 颜色相似度临界值,默认为16
  • +
  • algorithm <string> 颜色匹配算法,默认为rgb欧式距离
  • +
+

返回图片image在位置(x, y)处是否匹配到颜色color。有关threshold和algorithm的信息,参考findColor函数。

+

colors#

+
Stability: 2 - Stable

colors是颜色处理的工具对象。包含一些常用方法,包括android.graphics.Color的所有方法以及toString方法。

+

colors.toString(color)#

+
+

返回颜色值的字符串,格式为 #AARRGGBB。

+

colors.red(color)#

+
+

返回颜色color的R通道的值,范围0~255.

+

colors.green(color)#

+
+

返回颜色color的G通道的值,范围0~255.

+

colors.blue(color)#

+
+

返回颜色color的B通道的值,范围0~255.

+

colors.alpha(color)#

+
+

返回颜色color的Alpha通道的值,范围0~255.

+

colors.rgb(red, green, blue)#

+
+

返回这些颜色通道构成的整数颜色值。Alpha通道将是255(不透明)。

+

colors.argb(alpha, red, green, blue)#

+
+

返回这些颜色通道构成的整数颜色值。

+

Image#

+

[captureScreen][] 返回的对象。

+

Image.getWidth()#

+

返回以像素为单位图片宽度。

+

Image.getHeight()#

+

返回以像素为单位的图片高度。

+

Point#

+

findColor返回的对象。

+

Point.x#

+

横坐标。

+

Point.y#

+

纵坐标。

+ + +

Console#

+
Stability: 2 - Stable

控制台模块提供了一个和Web浏览器中相似的用于调试的控制台。用于输出一些调试信息、中间结果等。 +console模块中的一些函数也可以直接作为全局函数使用,例如log, print等。

+

console.show()#

+

显示控制台。这会显示一个控制台的悬浮窗(需要悬浮窗权限)。

+

console.clear()#

+

清空控制台。

+

console.log([data][, ...args])#

+
    +
  • data
  • +
  • ...args
  • +
+

打印到控制台,并带上换行符。 可以传入多个参数,第一个参数作为主要信息,其他参数作为类似于 printf(3) 中的代替值(参数都会传给 util.format())。

+
const count = 5;
+console.log('count: %d', count);
+// 打印: count: 5 到 stdout
+console.log('count:', count);
+// 打印: count: 5 到 stdout
+

详见 util.format()。

+

console.verbose([data][, ...args])#

+
    +
  • data
  • +
  • ...args
  • +
+

与console.log类似,但输出结果以灰色字体显示。输出优先级低于log,用于输出观察性质的信息。

+

console.info([data][, ...args])#

+
    +
  • data
  • +
  • ...args
  • +
+

与console.log类似,但输出结果以绿色字体显示。输出优先级高于log, 用于输出重要信息。

+

console.warn([data][, ...args])#

+
    +
  • data
  • +
  • ...args
  • +
+

与console.log类似,但输出结果以蓝色字体显示。输出优先级高于info, 用于输出警告信息。

+

console.error([data][, ...args])#

+
    +
  • data
  • +
  • ...args
  • +
+

与console.log类似,但输出结果以红色字体显示。输出优先级高于warn, 用于输出错误信息。

+

console.assert(value, message)#

+
    +
  • value <any> 要断言的布尔值
  • +
  • message <string> value为false时要输出的信息
  • +
+

断言。如果value为false则输出错误信息message并停止脚本运行。

+

console.input(data[, ...args])#

+
    +
  • data
  • +
  • ...args
  • +
+

与console.log一样输出信息,并在控制台显示输入框等待输入。按控制台的确认按钮后会将输入的字符串用eval计算后返回。

+

部分机型可能会有控制台不显示输入框的情况,属于bug。

+

例如:

+
var n = console.input("请输入一个数字:"); 
+//输入123之后:
+toast(n + 1);
+//显示124
+

console.rawInput(data[, ...args])#

+
    +
  • data
  • +
  • ...args
  • +
+

与console.log一样输出信息,并在控制台显示输入框等待输入。按控制台的确认按钮后会将输入的字符串直接返回。

+

部分机型可能会有控制台不显示输入框的情况,属于bug。

+

例如:

+
var n = console.input("请输入一个数字:"); 
+//输入123之后:
+toast(n + 1);
+//显示1231
+

print(text)#

+
+

在控制台中输出文本text。不会自动换行。

+ + +

Events#

+
Stability: 2 - Stable

events模块提供了监听手机通知、按键、触摸的接口。您可以用他配合自动操作函数完成自动化工作。

+

events本身是一个EventEmiiter, 但内置了一些事件、包括按键事件、通知事件、Toast事件等。

+

events.emitter()#

+

返回一个新的[EventEmitter][]。这个EventEmitter没有内置任何事件。

+

events.observeKey()#

+

启用按键监听,例如音量键、Home键。此函数使用无障碍服务实现,因此此函数会调用auto()确保无障碍服务启用。

+

只有这个函数成功执行后, [onKeyDown][], [onKeyUp][]等按键事件的监听才有效。

+

该函数在安卓4.3以上才能使用。

+

events.onKeyDown(keyName, listener)#

+
+

注册一个按键监听函数,当有keyName对应的按键被按下会调用该函数。可用的按键名称参见[Keys][]。

+

例如:

+
//启用按键监听
+events.observeKey();
+//监听音量上键按下
+events.onKeyDown("volume_up", function(event){
+    toast("音量上键被按下了");
+});
+//监听菜单键按下
+events.onKeyDown("menu", function(event){
+    toast("菜单键被按下了");
+    exit();
+});
+

events.onKeyUp(keyName, listener)#

+
+

注册一个按键监听函数,当有keyName对应的按键弹起会调用该函数。可用的按键名称参见Keys

+

一次完整的按键动作包括了按键按下和弹起。按下事件会在手指按下一个按键的"瞬间"触发, 弹起事件则在手指放开这个按键时触发。

+

例如:

+
//启用按键监听
+events.observeKey();
+//监听音量下键弹起
+events.onKeyDown("volume_down", function(event){
+    toast("音量上键弹起");
+});
+//监听Home键弹起
+events.onKeyDown("home", function(event){
+    toast("Home键弹起");
+    exit();
+});
+

events.onceKeyDown(keyName, listener)#

+
+

注册一个按键监听函数,当有keyName对应的按键被按下时会调用该函数,之后会注销该按键监听器。

+

也就是listener只有在onceKeyDown调用后的第一次按键事件被调用一次。

+

events.onceKeyUp(keyName, listener)#

+
+

注册一个按键监听函数,当有keyName对应的按键弹起时会调用该函数,之后会注销该按键监听器。

+

也就是listener只有在onceKeyUp调用后的第一次按键事件被调用一次。

+

events.removeAllKeyDownListeners(keyName)#

+
+

删除该按键的KeyDown(按下)事件的所有监听。

+

events.removeAllKeyUpListeners(keyName)#

+
+

删除该按键的KeyUp(弹起)事件的所有监听。

+

events.observeTouch()#

+

启用屏幕触摸监听。(需要root权限)

+

只有这个函数被成功执行后, 触摸事件的监听才有效。

+

没有root权限调用该函数则什么也不会发生。(注意: 这个行为未来可能会更改为抛出异常)

+

events.setTouchEventTimeout(timeout)#

+
    +
  • timeout <number> 两个触摸事件的最小间隔。单位毫秒。默认为10毫秒。如果number小于0,视为0处理。
  • +
+

设置两个触摸事件分发的最小时间间隔。

+

例如间隔为10毫秒的话,前一个触摸事件发生并被注册的监听器处理后,至少要过10毫秒才能分发和处理下一个触摸事件,这10毫秒之间的触摸将会被忽略。

+

建议在满足需要的情况下尽量提高这个间隔。一个简单滑动动作可能会连续触发上百个触摸事件,如果timeout设置过低可能造成事件拥堵。强烈建议不要设置timeout为0。

+

events.getTouchEventTimeout()#

+

返回触摸事件的最小时间间隔。

+

events.onTouch(listener)#

+
    +
  • listener <Function> 参数为[Point][]的函数
  • +
+

注册一个触摸监听函数。相当于on("touch", listener)

+

例如:

+
//启用触摸监听
+events.observeTouch();
+//注册触摸监听器
+events.onTouch(function(p){
+    //触摸事件发生时, 打印出触摸的点的坐标
+    log(p.x + ", " + p.y);
+});
+

events.removeAllTouchListeners()#

+

删除所有事件监听函数。

+

事件: 'key'#

+
    +
  • keyCode <number> 键值
  • +
  • event <KeyEvent> 事件
  • +
+

当有按键被按下或弹起时会触发该事件。 +例如:

+
auto();
+events.observeKey();
+events.on("key", function(keyCode, event){
+    //处理按键事件
+});
+

其中监听器的参数KeyCode包括:

+
    +
  • KeyEvent.KEYCODE_HOME 主页键
  • +
  • KeyEvent.KEYCODE_BACK 返回键
  • +
  • KeyEvent.KEYCODE_MENU 菜单键
  • +
  • KeyEvent.KEYCODE_VOLUMEUP 音量上键
  • +
  • KeyEvent.KEYCODE_VOLUMEDOWN 音量下键
  • +
+

事件: 'key_down'#

+
    +
  • keyCode <number> 键值
  • +
  • event <KeyEvent> 事件
  • +
+

当有按键被按下时会触发该事件。

+
auto();
+events.observeKey();
+events.on("key_down", function(keyCode, event){
+    //处理按键按下事件
+});
+

事件: 'key_up'#

+
    +
  • keyCode <number> 键值
  • +
  • event <KeyEvent> 事件
  • +
+

当有按键弹起时会触发该事件。

+
auto();
+events.observeKey();
+events.on("key_up", function(keyCode, event){
+    //处理按键弹起事件
+});
+

obverseNotification()#

+

开启通知(包括Toast)监听。

+

通知与Toast监听依赖于无障碍服务,因此这个函数会调用auto()来确保无障碍服务启用。

+

例如:

+
events.obverseNotification();
+events.onNotification(function(notification){
+    log(notification.getText());
+});
+events.onToast(function(toast){
+    log(toast.getText());
+});
+

事件: 'toast'#

+
    +
  • toast <Object>
      +
    • getText() 获取Toast的文本内容
    • +
    • getPackageName() 获取发出Toast的应用包名
    • +
    +
  • +
+

当有应用发出toast(气泡消息)时会触发该事件。但Auto.js软件本身的toast除外。 +例如,要记录发出所有toast的应用:

+
events.obverseNotification();
+events.onToast(function(toast){
+    log("Toast内容: " + toast.getText() + " 包名: " + toast.getPackageName());
+});
+

事件: 'notification'#

+
+

当有应用发出通知时会触发该事件。

+

例如:

+
events.observeNotification();
+events.on("notification", function(notification){
+    log(notification);
+});
+

注意: 这是一个实验性功能。实测只有某些情况下的通知才能被正确捕捉。

+

EventEmitter#

+
Stability: 2 - Stable

EventEmitter.defaultMaxListeners#

+

每个事件默认可以注册最多 10 个监听器。 单个 EventEmitter 实例的限制可以使用 emitter.setMaxListeners(n) 方法改变。 所有 EventEmitter 实例的默认值可以使用 EventEmitter.defaultMaxListeners 属性改变。

+

设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有 EventEmitter 实例,包括之前创建的。 因而,调用 emitter.setMaxListeners(n) 优先于 EventEmitter.defaultMaxListeners。

+

注意,与Node.js不同,这是一个硬性限制。 EventEmitter 实例不允许添加更多的监听器,监听器超过最大数量时会抛出TooManyListenersException。

+
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
+emitter.once('event', () => {
+  // 做些操作
+  emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
+});
+

EventEmitter.addListener(eventName, listener)#

+
+

emitter.on(eventName, listener) 的别名。

+

EventEmitter.emit(eventName[, ...args])#

+
    +
  • eventName <any>
  • +
  • args <any>
  • +
+

按监听器的注册顺序,同步地调用每个注册到名为 eventName 事件的监听器,并传入提供的参数。

+

如果事件有监听器,则返回 true ,否则返回 false。

+

EventEmitter.eventNames()#

+

返回一个列出触发器已注册监听器的事件的数组。 数组中的值为字符串或符号。

+
const myEE = events.emitter();
+myEE.on('foo', () => {});
+myEE.on('bar', () => {});
+
+const sym = Symbol('symbol');
+myEE.on(sym, () => {});
+
+console.log(myEE.eventNames());
+// 打印: [ 'foo', 'bar', Symbol(symbol) ]
+

EventEmitter.getMaxListeners()#

+

返回 EventEmitter 当前的最大监听器限制值,该值可以通过 emitter.setMaxListeners(n) 设置或默认为 EventEmitter.defaultMaxListeners。

+

EventEmitter.listenerCount(eventName)#

+
    +
  • eventName <string> 正在被监听的事件名
  • +
+

返回正在监听名为 eventName 的事件的监听器的数量。

+

EventEmitter.listeners(eventName)#

+
+

返回名为 eventName 的事件的监听器数组的副本。

+
server.on('connection', (stream) => {
+  console.log('someone connected!');
+});
+console.log(util.inspect(server.listeners('connection')));
+// 打印: [ [Function] ]
+

EventEmitter.on(eventName, listener)#

+
    +
  • eventName <any> 事件名
  • +
  • listener <Function> 回调函数
  • +
+

添加 listener 函数到名为 eventName 的事件的监听器数组的末尾。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。

+
server.on('connection', (stream) => {
+  console.log('有连接!');
+});
+

返回一个 EventEmitter 引用,可以链式调用。

+

默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependListener() 方法可用于将事件监听器添加到监听器数组的开头。

+
const myEE = events.emitter();
+myEE.on('foo', () => console.log('a'));
+myEE.prependListener('foo', () => console.log('b'));
+myEE.emit('foo');
+// 打印:
+//   b
+//   a
+

EventEmitter.once(eventName, listener)#

+
    +
  • eventName <any> 事件名
  • +
  • listener <Function> 回调函数
  • +
+

添加一个单次 listener 函数到名为 eventName 的事件。 下次触发 eventName 事件时,监听器会被移除,然后调用。

+
server.once('connection', (stream) => {
+  console.log('首次调用!');
+});
+

返回一个 EventEmitter 引用,可以链式调用。

+

默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependOnceListener() 方法可用于将事件监听器添加到监听器数组的开头。

+
const myEE = events.emitter();
+myEE.once('foo', () => console.log('a'));
+myEE.prependOnceListener('foo', () => console.log('b'));
+myEE.emit('foo');
+// 打印:
+//   b
+//   a
+

EventEmitter.prependListener(eventName, listener)#

+
    +
  • eventName <any> 事件名
  • +
  • listener <Function> 回调函数
  • +
+

添加 listener 函数到名为 eventName 的事件的监听器数组的开头。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。

+
server.prependListener('connection', (stream) => {
+  console.log('有连接!');
+});
+

返回一个 EventEmitter 引用,可以链式调用。

+

EventEmitter.prependOnceListener(eventName, listener)#

+
    +
  • eventName <any> 事件名
  • +
  • listener <Function> 回调函数
  • +
+

添加一个单次 listener 函数到名为 eventName 的事件的监听器数组的开头。 下次触发 eventName 事件时,监听器会被移除,然后调用。

+
server.prependOnceListener('connection', (stream) => {
+  console.log('首次调用!');
+});
+

返回一个 EventEmitter 引用,可以链式调用。

+

EventEmitter.removeAllListeners([eventName])#

+
    +
  • eventName <any>
  • +
+

移除全部或指定 eventName 的监听器。

+

注意,在代码中移除其他地方添加的监听器是一个不好的做法,尤其是当 EventEmitter 实例是其他组件或模块创建的。

+

返回一个 EventEmitter 引用,可以链式调用。

+

EventEmitter.removeListener(eventName, listener)#

+
+

从名为 eventName 的事件的监听器数组中移除指定的 listener。

+
const callback = (stream) => {
+  console.log('有连接!');
+};
+server.on('connection', callback);
+// ...
+server.removeListener('connection', callback);
+

removeListener 最多只会从监听器数组里移除一个监听器实例。 如果任何单一的监听器被多次添加到指定 eventName 的监听器数组中,则必须多次调用 removeListener 才能移除每个实例。

+

注意,一旦一个事件被触发,所有绑定到它的监听器都会按顺序依次触发。 这意味着,在事件触发后、最后一个监听器完成执行前,任何 removeListener() 或 removeAllListeners() 调用都不会从 emit() 中移除它们。 随后的事件会像预期的那样发生。

+
const myEmitter = events.emitter();
+
+const callbackA = () => {
+  console.log('A');
+  myEmitter.removeListener('event', callbackB);
+};
+
+const callbackB = () => {
+  console.log('B');
+};
+
+myEmitter.on('event', callbackA);
+
+myEmitter.on('event', callbackB);
+
+// callbackA 移除了监听器 callbackB,但它依然会被调用。
+// 触发是内部的监听器数组为 [callbackA, callbackB]
+myEmitter.emit('event');
+// 打印:
+//   A
+//   B
+
+// callbackB 被移除了。
+// 内部监听器数组为 [callbackA]
+myEmitter.emit('event');
+// 打印:
+//   A
+

因为监听器是使用内部数组进行管理的,所以调用它会改变在监听器被移除后注册的任何监听器的位置索引。 虽然这不会影响监听器的调用顺序,但意味着由 emitter.listeners() 方法返回的监听器数组副本需要被重新创建。

+

返回一个 EventEmitter 引用,可以链式调用。

+

EventEmitter.setMaxListeners(n)#

+
+

默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 此限制有助于寻找内存泄露。 但是,并不是所有的事件都要被限为 10 个。 emitter.setMaxListeners() 方法允许修改指定的 EventEmitter 实例的限制。 值设为 Infinity(或 0)表明不限制监听器的数量。

+

返回一个 EventEmitter 引用,可以链式调用。

+

KeyEvent#

+
Stability: 2 - Stable

KeyEvent.getAction()#

+

返回事件的动作。包括:

+
    +
  • KeyEvent.ACTION_DOWN 按下事件
  • +
  • KeyEvent.ACTION_UP 弹起事件
  • +
+

KeyEvent.getKeyCode()#

+

返回按键的键值。包括:

+
    +
  • KeyEvent.KEYCODE_HOME 主页键
  • +
  • KeyEvent.KEYCODE_BACK 返回键
  • +
  • KeyEvent.KEYCODE_MENU 菜单键
  • +
  • KeyEvent.KEYCODE_VOLUME_UP 音量上键
  • +
  • KeyEvent.KEYCODE_VOLUME_DOWN 音量下键
  • +
+

KeyEvent.getEventTime()#

+

返回事件发生的时间戳。返回值的类型是number。

+

KeyEvent.getDownTime()#

+

返回最近一次按下事件的时间戳。如果本身是按下事件,则与getEventTime()相同。

+

KeyEvent.keyCodeToString(keyCode)#

+

把键值转换为字符串。例如KEYCODE_HOME转换为"KEYCODE_HOME"。

+

Keys#

+
Stability: 2 - Stable

按键事件中所有可用的按键名称为:

+
    +
  • volume_up 音量上键
  • +
  • volume_down 音量下键
  • +
  • home 主屏幕键
  • +
  • back 返回键
  • +
  • menu 菜单键
  • +
+ + +

Timers#

+
Stability: 2 - Stable

timers 模块暴露了一个全局的 API,用于在某个未来时间段调用调度函数。 因为定时器函数是全局的,所以使用该 API 无需调用 timers.*

+

Auto.js 中的计时器函数实现了与 Web 浏览器提供的定时器类似的 API,除了它使用了一个不同的内部实现,它是基于 Android Looper-Handler消息循环机制构建的。其实现机制与Node.js比较相似。

+

setImmediate(callback[, ...args])#

+
    +
  • callback <Function> 在Looper循环的当前回合结束时要调用的函数。
  • +
  • ...args <any> 当调用 callback 时要传入的可选参数。
  • +
+

预定立即执行的 callback,它是在 I/O 事件的回调之后被触发。 返回一个用于 clearImmediate() 的 id。

+

当多次调用 setImmediate() 时,callback 函数会按照它们被创建的顺序依次执行。 每次事件循环迭代都会处理整个回调队列。 如果一个立即定时器是被一个正在执行的回调排入队列的,则该定时器直到下一次事件循环迭代才会被触发。

+

setInterval(callback, delay[, ...args])#

+
    +
  • callback <Function> 当定时器到点时要调用的函数。
  • +
  • delay <number> 调用 callback 之前要等待的毫秒数。
  • +
  • ...args <any> 当调用 callback 时要传入的可选参数。
  • +
+

预定每隔 delay 毫秒重复执行的 callback。 返回一个用于 clearInterval() 的 id。

+

当 delay 小于 0 时,delay 会被设为 0。

+

setTimeout(callback, delay[, ...args])#

+
    +
  • callback <Function> 当定时器到点时要调用的函数。
  • +
  • delay <number> 调用 callback 之前要等待的毫秒数。
  • +
  • ...args <any> 当调用 callback 时要传入的可选参数。
  • +
+

预定在 delay 毫秒之后执行的单次 callback。 返回一个用于 clearTimeout() 的 id。

+

callback 可能不会精确地在 delay 毫秒被调用。 Auto.js 不能保证回调被触发的确切时间,也不能保证它们的顺序。 回调会在尽可能接近所指定的时间上调用。

+

当 delay 小于 0 时,delay 会被设为 0。

+

setImmediate()、setInterval() 和 setTimeout() 方法每次都会返回表示预定的计时器的id。 它们可用于取消定时器并防止触发。

+

clearImmediate(id)#

+
    +
  • id <number> 一个 setImmediate() 返回的 id。
  • +
+

取消一个由 setImmediate() 创建的 Immediate 对象。

+

clearInterval(id)#

+
    +
  • id <number> 一个 setInterval() 返回的 id。
  • +
+

取消一个由 setInterval() 创建的 Timeout 对象。

+

clearTimeout(id)#

+
    +
  • id <number> 一个 setTimeout() 返回的 id。
  • +
+

取消一个由 setTimeout() 创建的 Timeout 对象。

+ + +

shell即Unix Shell,在类Unix系统提供与操作系统交互的一系列命令。

+

很多程序可以用来执行shell命令,例如终端模拟器。

+

在Auto.js大致等同于用adb执行命令"adb shell"。其实现包括两种方式:

+
    +
  • 通过java.lang.Runtime.exec执行(shell, Tap, Home等函数)
  • +
  • 通过内嵌终端模拟器执行(RootAutomator, Shell等对象)
  • +
+

shell函数#

+
Stability: 2 - Stable

shell(cmd[, root = false])#

+
    +
  • cmd <string> 要执行的命令
  • +
  • root <Boolean> 是否以root权限运行,默认为false。
  • +
+

返回运行一个对象表示命令的执行结果。其属性如下:

+
    +
  • code <number> 返回码。执行成功时为0,失败时为非0的数字。
  • +
  • result <string> 运行结果(stdout输出结果)
  • +
  • error \ 运行的错误信息(stderr输出结果)。例如执行需要root权限的命令但没有授予root权限会返回错误信息"Permission denied"。
  • +
+

示例(强制停止微信) :

+
var result = shell("am force-stop com.tencent.mm", true);
+log(result);
+console.show();
+if(result.code == 0){
+  toast("执行成功");
+}else{
+  toast("执行失败!请到控制台查看错误信息");
+}
+

Shell#

+
Stability: 2 - Stable

shell函数通过用来一次性执行单条命令并获取结果。如果有多条命令需要执行,用Shell对象的效率更高。这是因为,每次运行shell函数都会打开一个单独的shell进程并在运行结束后关闭他,这个过程需要一定的时间;而Shell对象自始至终使用同一个shell进程。

+

Shell(root = false)#

+
    +
  • root <Boolean> 是否以root权限运行一个shell进程。这将会影响其后使用该Shell对象执行的命令的权限
  • +
+

Shell对象的"构造函数"。

+
var sh = new Shell(true);
+sh.exec("am force-stop com.tencent.mm");
+sh.exit();
+

Shell.exec(cmd)#

+
+

执行命令cmd。该函数不会返回任何值。

+

注意,命令执行是"异步"的、非阻塞的。也就是不会等待命令完成后才继续向下执行。

+

尽管这样的设计使用起来有很多不便之处,但受限于终端模拟器,暂时没有解决方式;如果后续能找到解决方案,则将提供Shell.execAndWaitFor函数。

+

Shell.exit()#

+

直接退出shell。这意味着正在执行的命令会被强制退出。

+

Shell.exitAndWaitFor()#

+

执行"exit"命令并等待执行命令执行完成、退出shell。

+

此函数会执行exit命令来正常退出shell。

+

Shell.setCallback(callback)#

+
+

设置该Shell的回调函数,以便监听Shell的输出。可以包括以下属性:

+
    +
  • onOutput <function> 每当shell有新的输出时便会调用该函数。其参数是一个字符串。
  • +
  • onNewLine <function> 每当shell有新的一行输出时便会调用该函数。其参数是一个字符串(不包括最后的换行符)。
  • +
+

例如:

+
var sh = new Shell();
+sh.setCallback({
+    onNewLine: function(line){
+        log(line);
+    }
+})
+while(true){
+    var cmd = dialogs.rawInput("请输入要执行的命令,输入exit退出");
+    if(cmd == "exit"){
+        break;
+    }
+    sh.exec(cmd);
+}
+sh.exit();
+

附录: shell命令简介#

+

以下关于shell命令的资料来自AndroidStudio用户指南:Shell命令

+

am命令#

+

am命令即Activity Manager命令,用于管理应用程序活动、服务等。

+

以下命令均以"am "开头,例如"shell(\"am start -p com.tencent.mm\");"(启动微信)

+

start [options] intent#

+

启动 intent 指定的 Activity(应用程序活动)。
请参阅 intent 参数的规范

+

选项包括:

+
    +
  • -D:启用调试。
  • +
  • -W:等待启动完成。
  • +
  • --start-profiler file:启动分析器并将结果发送到 file。
  • +
  • -P file:类似于 --start-profiler,但当应用进入空闲状态时分析停止。
  • +
  • -R count:重复 Activity 启动 count 次数。在每次重复前,将完成顶部 Activity。
  • +
  • -S:启动 Activity 前强行停止目标应用。
  • +
  • --opengl-trace:启用 OpenGL 函数的跟踪。
  • +
  • --user user_id | current:指定要作为哪个用户运行;如果未指定,则作为当前用户运行。
  • +
+

startservice [options] intent#

+

启动 intent 指定的 Service(服务)。
请参阅 intent 参数的规范
选项包括:

+
    +
  • --user user_id | current:指定要作为哪个用户运行;如果未指定,则作为当前用户运行。
  • +
+

force-stop package#

+

强行停止与 package(应用包名)关联的所有应用。

+

kill [options] package#

+

终止与 package(应用包名)关联的所有进程。此命令仅终止可安全终止且不会影响用户体验的进程。
选项包括:

+
    +
  • --user user_id | all | current:指定将终止其进程的用户;如果未指定,则终止所有用户的进程。
  • +
+

kill-all#

+

终止所有后台进程。

+

broadcast [options] intent#

+

发出广播 intent。 +请参阅 intent 参数的规范

+

选项包括:

+
    +
  • [--user user_id | all | current]:指定要发送到的用户;如果未指定,则发送到所有用户。
  • +
+

instrument [options] component#

+

使用 Instrumentation 实例启动监控。通常,目标 component 是表单 test_package/runner_class。
选项包括:

+
    +
  • -r:输出原始结果(否则对 report_key_streamresult 进行解码)。与 [-e perf true] 结合使用以生成性能测量的原始输出。
  • +
  • -e name value:将参数 name 设为 value。对于测试运行器,通用表单为 -e testrunner_flag value[,value...]。
  • +
  • -p file:将分析数据写入 file。
  • +
  • -w:先等待仪器完成,然后再返回。测试运行器需要使用此选项。
  • +
  • --no-window-animation:运行时关闭窗口动画。
  • +
  • --user user_id | current:指定仪器在哪个用户中运行;如果未指定,则在当前用户中运行。
  • +
  • profile start process file 启动 process 的分析器,将结果写入 file。
  • +
  • profile stop process 停止 process 的分析器。
  • +
+

dumpheap [options] process file#

+

转储 process 的堆,写入 file。

+

选项包括:

+
    +
  • --user [user_id|current]:提供进程名称时,指定要转储的进程用户;如果未指定,则使用当前用户。
  • +
  • -n:转储原生堆,而非托管堆。
  • +
  • set-debug-app [options] package 将应用 package 设为调试。
  • +
+

选项包括:

+
    +
  • -w:应用启动时等待调试程序。
  • +
  • --persistent:保留此值。
  • +
  • clear-debug-app 使用 set-debug-app 清除以前针对调试用途设置的软件包。
  • +
+

monitor [options] 启动对崩溃或 ANR 的监控。#

+

选项包括:

+
    +
  • --gdb:在崩溃/ANR 时在给定端口上启动 gdbserv。

    screen-compat <on> | <off> package#

    +控制 package 的屏幕兼容性模式。
  • +
+

display-size [reset|widthxheight]#

+

替换模拟器/设备显示尺寸。此命令对于在不同尺寸的屏幕上测试您的应用非常有用,它支持使用大屏设备模仿小屏幕分辨率(反之亦然)。
示例:

+
shell("am display-size 1280x800", true);
+

display-density dpi#

+

替换模拟器/设备显示密度。此命令对于在不同密度的屏幕上测试您的应用非常有用,它支持使用低密度屏幕在高密度环境环境上进行测试(反之亦然)。
示例:

+
shell("am display-density 480", true);
+

to-uri intent#

+

将给定的 intent 规范以 URI 的形式输出。 +请参阅 intent 参数的规范

+

to-intent-uri intent#

+

将给定的 intent 规范以 intent:URI 的形式输出。 +请参阅 intent 参数的规范。

+

intent参数的规范#

+

对于采用 intent 参数的 am 命令,您可以使用以下选项指定 intent:

+
    +
  • -a action
    指定 intent 操作,如“android.intent.action.VIEW”。此指定只能声明一次。
  • +
  • -d data_uri
    指定 intent 数据 URI,如“content://contacts/people/1”。此指定只能声明一次。
  • +
  • -t mime_type
    指定 intent MIME 类型,如“image/png”。此指定只能声明一次。
  • +
  • -c category
    指定 intent 类别,如“android.intent.category.APP_CONTACTS”。
  • +
  • -n component
    指定带有软件包名称前缀的组件名称以创建显式 intent,如“com.example.app/.ExampleActivity”。
  • +
  • -f flags
    将标志添加到 setFlags() 支持的 intent。
  • +
  • --esn extra_key
    添加一个 null extra。URI intent 不支持此选项。
  • +
  • -e|--es extra_key extra_string_value
    添加字符串数据作为键值对。
  • +
  • --ez extra_key extra_boolean_value
    添加布尔型数据作为键值对。
  • +
  • --ei extra_key extra_int_value
    添加整数型数据作为键值对。
  • +
  • --el extra_key extra_long_value
    添加长整型数据作为键值对。
  • +
  • --ef extra_key extra_float_value
    添加浮点型数据作为键值对。
  • +
  • --eu extra_key extra_uri_value
    添加 URI 数据作为键值对。
  • +
  • --ecn extra_key extra_component_name_value
    添加组件名称,将其作为 ComponentName 对象进行转换和传递。
  • +
  • --eia extra_key extra_int_value[,extra_int_value...]
    添加整数数组。
  • +
  • --ela extra_key extra_long_value[,extra_long_value...]
    添加长整型数组。
  • +
  • --efa extra_key extra_float_value[,extra_float_value...]
    添加浮点型数组。
  • +
  • --grant-read-uri-permission
    包含标志 FLAG_GRANT_READ_URI_PERMISSION。
  • +
  • --grant-write-uri-permission
    包含标志 FLAG_GRANT_WRITE_URI_PERMISSION。
  • +
  • --debug-log-resolution
    包含标志 FLAG_DEBUG_LOG_RESOLUTION。
  • +
  • --exclude-stopped-packages
    包含标志 FLAG_EXCLUDE_STOPPED_PACKAGES。
  • +
  • --include-stopped-packages
    包含标志 FLAG_INCLUDE_STOPPED_PACKAGES。
  • +
  • --activity-brought-to-front
    包含标志 FLAG_ACTIVITY_BROUGHT_TO_FRONT。
  • +
  • --activity-clear-top
    包含标志 FLAG_ACTIVITY_CLEAR_TOP。
  • +
  • --activity-clear-when-task-reset
    包含标志 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET。
  • +
  • --activity-exclude-from-recents
    包含标志 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS。
  • +
  • --activity-launched-from-history
    包含标志 FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY。
  • +
  • --activity-multiple-task
    包含标志 FLAG_ACTIVITY_MULTIPLE_TASK。
  • +
  • --activity-no-animation
    包含标志 FLAG_ACTIVITY_NO_ANIMATION。
  • +
  • --activity-no-history
    包含标志 FLAG_ACTIVITY_NO_HISTORY。
  • +
  • --activity-no-user-action
    包含标志 FLAG_ACTIVITY_NO_USER_ACTION。
  • +
  • --activity-previous-is-top
    包含标志 FLAG_ACTIVITY_PREVIOUS_IS_TOP。
  • +
  • --activity-reorder-to-front
    包含标志 FLAG_ACTIVITY_REORDER_TO_FRONT。
  • +
  • --activity-reset-task-if-needed
    包含标志 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED。
  • +
  • --activity-single-top
    包含标志 FLAG_ACTIVITY_SINGLE_TOP。
  • +
  • --activity-clear-task
    包含标志 FLAG_ACTIVITY_CLEAR_TASK。
  • +
  • --activity-task-on-home
    包含标志 FLAG_ACTIVITY_TASK_ON_HOME。
  • +
  • --receiver-registered-only
    包含标志 FLAG_RECEIVER_REGISTERED_ONLY。
  • +
  • --receiver-replace-pending
    包含标志 FLAG_RECEIVER_REPLACE_PENDING。
  • +
  • --selector
    需要使用 -d 和 -t 选项以设置 intent 数据和类型。

    URI component package#

    +如果不受上述某一选项的限制,您可以直接指定 URI、软件包名称和组件名称。当参数不受限制时,如果参数包含一个“:”(冒号),则此工具假定参数是一个 URI;如果参数包含一个“/”(正斜杠),则此工具假定参数是一个组件名称;否则,此工具假定参数是一个软件包名称。
  • +
+

应用包名#

+

所谓应用包名,是唯一确定应用的标识。例如微信的包名是"com.tencent.mm", QQ的包名是"com.tencent.mobileqq"。
要获取一个应用的包名,可以通过函数getPackageName(appName)获取。参见帮助->其他一般函数。

+

pm命令#

+

pm命令用于管理应用程序,例如卸载应用、冻结应用等。
以下命令均以"pm "开头,例如"shell(\"pm disable com.tencent.mm\");"(冻结微信)

+

list packages [options] filter#

+

输出所有软件包,或者,仅输出包名称包含 filter 中的文本的软件包。
选项:

+
    +
  • -f:查看它们的关联文件。
  • +
  • -d:进行过滤以仅显示已停用的软件包。
  • +
  • -e:进行过滤以仅显示已启用的软件包。
  • +
  • -s:进行过滤以仅显示系统软件包。
  • +
  • -3:进行过滤以仅显示第三方软件包。
  • +
  • -i:查看软件包的安装程序。
  • +
  • -u:也包括卸载的软件包。
  • +
  • --user user_id:要查询的用户空间。
  • +
+

list permission-groups#

+

输出所有已知的权限组。

+

list permissions [options] group#

+

输出所有已知权限,或者,仅输出 group 中的权限。
选项:

+
    +
  • -g:按组加以组织。
  • +
  • -f:输出所有信息。
  • +
  • -s:简短摘要。
  • +
  • -d:仅列出危险权限。
  • +
  • -u:仅列出用户将看到的权限。
  • +
+

list instrumentation [options]#

+

列出所有测试软件包。
选项:

+
    +
  • -f:列出用于测试软件包的 APK 文件。
  • +
  • target_package:列出仅用于此应用的测试软件包。
  • +
+

list features#

+

输出系统的所有功能。

+

list libraries#

+

输出当前设备支持的所有库。

+

list users#

+

输出系统上的所有用户。

+

path package#

+

输出给定 package 的 APK 的路径。

+

install [options] path#

+

将软件包(通过 path 指定)安装到系统。
选项:

+
    +
  • -l:安装具有转发锁定功能的软件包。
  • +
  • -r:重新安装现有应用,保留其数据。
  • +
  • -t:允许安装测试 APK。
  • +
  • -i installer_package_name:指定安装程序软件包名称。
  • +
  • -s:在共享的大容量存储(如 sdcard)上安装软件包。
  • +
  • -f:在内部系统内存上安装软件包。
  • +
  • -d:允许版本代码降级。
  • +
  • -g:授予应用清单文件中列出的所有权限。
  • +
+

uninstall [options] package#

+

从系统中卸载软件包。
选项:

+
    +
  • -k:移除软件包后保留数据和缓存目录。

    clear package#

    +删除与软件包关联的所有数据。
  • +
+

enable package_or_component#

+

启用给定软件包或组件(作为“package/class”写入)。

+

disable package_or_component#

+

停用给定软件包或组件(作为“package/class”写入)。

+

disable-user [options] package_or_component#

+

选项:

+
    +
  • --user user_id:要停用的用户。

    grant package_name permission#

    +向应用授予权限。在运行 Android 6.0(API 级别 23)及更高版本的设备上,可以是应用清单中声明的任何权限。在运行 Android 5.1(API 级别 22)和更低版本的设备上,必须是应用定义的可选权限。
  • +
+

revoke package_name permission#

+

从应用中撤销权限。在运行 Android 6.0(API 级别 23)及更高版本的设备上,可以是应用清单中声明的任何权限。在运行 Android 5.1(API 级别 22)和更低版本的设备上,必须是应用定义的可选权限。

+

set-install-location location#

+

更改默认安装位置。位置值:

+
    +
  • 0:自动—让系统决定最佳位置。
  • +
  • 1:内部—安装在内部设备存储上。
  • +
  • 2:外部—安装在外部介质上。
  • +
+
+

注:此命令仅用于调试目的;使用此命令会导致应用中断和其他意外行为。

+
+

get-install-location#

+

返回当前安装位置。返回值:

+
    +
  • 0 [auto]:让系统决定最佳位置。
  • +
  • 1 [internal]:安装在内部设备存储上
  • +
  • 2 [external]:安装在外部介质上
  • +
+

set-permission-enforced permission [true|false]#

+

指定是否应强制执行给定的权限。

+

trim-caches desired_free_space#

+

减少缓存文件以达到给定的可用空间。

+

create-user user_name#

+

使用给定的 user_name 创建新用户,输出新用户的标识符。

+

remove-user user_id#

+

移除具有给定的 user_id 的用户,删除与该用户关联的所有数据。

+

get-max-users#

+

输出设备支持的最大用户数。

+

其他命令#

+

进行屏幕截图#

+

screencap 命令是一个用于对设备显示屏进行屏幕截图的 shell 实用程序。在 shell 中,此语法为:

+
screencap filename
+

例如:

+
$ shell("screencap /sdcard/screen.png");
+

列表文件#

+
ls filepath
+

例如:

+
log(shell("ls /system/bin").result);
+
+ + + +

Files#

+
Stability: 2 - Stable

files模块提供了一些常见的文件处理,包括文件读写、移动、复制、删掉等。

+

files.isFile(path)#

+
+

返回路径path是否是文件。

+

files.isDir(path)#

+
+

返回路径path是否是文件夹。

+

files.isEmptyDir(path)#

+
+

返回文件夹path是否为空文件夹。如果该路径并非文件夹,则直接返回false。

+

files.join(parent, child)#

+
+

连接两个路径并返回,例如files.join("/sdcard/", "1.txt")返回"/sdcard/1.txt"。

+

files.create(path)#

+
+

创建一个文件并返回是否创建成功。

+

files.createIfNotExists(path)#

+
+

创建一个文件并返回是否创建成功。

+

files.exists(path)#

+
+

返回在路径path处的文件是否存在。

+

files.ensureDir(path)#

+
+

确保路径path所在的文件夹存在。

+

例如对于路径"/sdcard/Download/ABC/1.txt",如果/Download/文件夹不存在,则会先创建Download,再创建ABC文件夹。

+

files.read(path[, encoding = "utf-8"])#

+
+

读取文件path的所有内容并返回。

+

files.write(path, text[, encoding = "utf-8"])#

+
+

把text写入到文件path中。如果文件存在则覆盖,不存在则创建。

+

files.copy(fromPath, toPath)#

+
    +
  • fromPath <string> 要复制的原文件路径
  • +
  • toPath <string> 复制到的文件路径
  • +
+

复制文件。例如files.copy("/sdcard/1.txt", "/sdcard/Download/1.txt")

+

files.move(fromPath, toPath)#

+
    +
  • fromPath <string> 要移动的原文件路径
  • +
  • toPath <string> 移动到的文件路径
  • +
+

移动文件,返回是否移动成功。例如files.move("/sdcard/1.txt", "/sdcard/Download/1.txt")会把1.txt文件从sd卡根目录移动到Download文件夹。

+

files.rename(path, newName)#

+
    +
  • path <string> 要重命名的原文件路径
  • +
  • newName <string> 要重命名的新文件名
  • +
+

重命名文件,并返回是否重命名成功。例如files.rename("/sdcard/1.txt", "2.txt")

+

files.renameWithoutExtension(path, newName)#

+
    +
  • path <string> 要重命名的原文件路径
  • +
  • newName <string> 要重命名的新文件名
  • +
+

重命名文件,不包含拓展名,并返回是否重命名成功。例如files.rename("/sdcard/1.txt", "2")会把1.txt重命名为2.txt。

+

files.getName(path)#

+
+

返回文件的文件名。例如files.getName("/sdcard/1.txt")返回"1.txt"。

+

files.getNameWithoutExtension(path)#

+
+

返回不含拓展名的文件的文件名。例如files.getName("/sdcard/1.txt")返回"1"。

+

files.getExtension(path)#

+
+

返回文件的拓展名。例如files.getExtension("/sdcard/1.txt")返回"txt"。

+

files.remove(path)#

+
+

删除文件或空文件夹,返回是否删除成功。

+

files.removeDir(path)#

+
+

删除文件夹,如果文件夹不为空,则删除该文件夹的所有内容再删除该文件夹,返回是否全部删除成功。

+

files.getSdcardPath()#

+

返回SD卡路径。所谓SD卡,即外部存储器。

+

files.listDir(path[, filter])#

+
    +
  • path <string> 路径
  • +
  • filter <Function> 过滤函数,可选。接收一个String参数(文件名),返回一个Boolean值。
  • +
+

列出文件夹path下的满足条件的文件和文件夹的名称的数组。如果不加filter参数,则返回所有文件和文件夹。

+

例如,获取sdcard目录下的txt文件为

+
var txtFiles = files.listDir("/sdcard/", function(name){
+    return name.endsWith(".txt") && files.isFile("/sdcard/" + name);
+});
+

open(path[, mode = "r", encoding = "utf-8", bufferSize = 8192])#

+
    +
  • path <string> 文件路径,例如"/sdcard/1.txt"。
  • +
  • mode <string> 文件打开模式,包括:
      +
    • "r": 只读模式。该模式下只能对文件执行文本读取操作。
    • +
    • "w": 只写模式。该模式下只能对文件执行文本覆盖写入操作。
    • +
    • "a": 附加模式。该模式下将会把写入的文本附加到文件末尾。
      目前暂不支持二进制模式,随机读写模式。
    • +
    +
  • +
  • encoding <string> 字符编码。
  • +
  • bufferSize <Number> 文件读写的缓冲区大小。
  • +
+

打开一个文件。根据打开模式返回不同的文件对象。包括:

+
    +
  • "r": 返回一个ReadableTextFile对象。
  • +
  • "w", "a": 返回一个WritableTextFile对象。
  • +
+

对于"w"模式,如果文件并不存在,则会创建一个,已存在则会清空该文件内容;其他模式文件不存在会抛出FileNotFoundException。

+

ReadableTextFile#

+

可读文件对象。

+

ReadableTextFile.read()#

+

返回该文件剩余的所有内容的字符串。

+

ReadableTextFile.read(maxCount)#

+
    +
  • maxCount <Number> 最大读取的字符数量
  • +
+

读取该文件接下来最长为maxCount的字符串并返回。即使文件剩余内容不足maxCount也不会出错。

+

ReadableTextFile.readline()#

+

读取一行并返回(不包含换行符)。

+

ReadableTextFile.readlines()#

+

读取剩余的所有行,并返回它们按顺序组成的字符串数组。

+

close()#

+

关闭该文件。

+

打开一个文件不再使用时务必关闭

+

PWritableTextFile#

+

可写文件对象。

+

PWritableTextFile.write(text)#

+
+

把文本内容text写入到文件中。

+

PWritableTextFile.writeline(line)#

+
+

把文本line写入到文件中并写入一个换行符。

+

PWritableTextFile.writelines(lines)#

+
+

把很多行写入到文件中....

+

PWritableTextFile.flush()#

+

把缓冲区内容输出到文件中。

+

PWritableTextFile.close()#

+

关闭文件。同时会被缓冲区内容输出到文件。

+

打开一个文件写入后,不再使用时务必关闭,否则文件可能会丢失

+ + +

App#

+

app模块提供一系列函数,用于与其他应用的交互。例如打开文件、拍照、发送邮件等。

+

同时提供了方便的基础函数startActivity和sendBroadcast,用他们可完成app模块没有内置的和其他应用的交互。

+

app.viewFile(path)#

+
+

用其他应用查看文件。

+

app.editFile(path)#

+
+

用其他应用编辑文件。

+

app.uninstall(packageName)#

+
+

卸载应用。

+

app.openUrl(url)#

+
+

用浏览器打开网站url。

+

app.takePhoto(path)#

+
+

调用相机应用拍照,完成后保存到路径path。

+

app.sendEmail(options)#

+
    +
  • options <Object> 发送邮件的参数。包括:
      +
    • email <string> | <Array> 收件人的邮件地址。如果有多个收件人,则用字符串数组表示
    • +
    • cc <string> | <Array> 抄送收件人的邮件地址。如果有多个抄送收件人,则用字符串数组表示
    • +
    • bcc <string> | <Array> 密送收件人的邮件地址。如果有多个密送收件人,则用字符串数组表示
    • +
    • subject <string> 邮件主题(标题)
    • +
    • text <string> 邮件正文
    • +
    • attachment <string> | <Array> 附件的路径。如果有多个附件,则用字符串数组表示
    • +
    +
  • +
+

根据选项options调用邮箱应用发送邮件。这些选项均是可选的。

+

app.intent(intent)#

+
    +
  • intent <Object> 一个表示Intent对象,其属性可以包括:
      +
    • action <string> 这个Intent的Action,比如"android.intent.action.SEND"
    • +
    • type <string> 这个Intent的MimeType,比如"text/plain"
    • +
    • data <string> 这个Intent的Data(Uri),可以是文件路径或者Url等。
    • +
    • category \ 这个Intent的Category的字符串数组。
    • +
    • packageName <string> 目标包名
    • +
    • className <string> 目标Activity或Service等组件的名称
    • +
    • extras <Object> 以键值对构成的这个Intent的Extras。
    • +
    +
  • +
+

返回用intent对象构造的android.content.Intent对象。

+

例如:

+
var i = app.intent({
+    action: "android.intent.action.VIEW",
+    type: "text/plain",
+    data: "file:///sdcard/1.txt",
+});
+

如果你看了一脸懵逼,请百度安卓Intent

+

app.startActivity(intent)#

+
    +
  • intent <Object> 与app.intent函数的参数一样的intent对象。
  • +
+

相当于context.startActivity(intent)。

+

app.sendBroadcast(intent)#

+
    +
  • intent <Object> 与app.intent函数的参数一样的intent对象。
  • +
+

相当于context.sendBroadcast(intent)。

+ + +

Engines#

+
Stability: 2 - Stable

engines模块包含了一些与脚本引擎有关的函数,包括运行其他脚本,关闭脚本等。

+

engines.execScript(name, script[, config])#

+
    +
  • name <string> 要运行的脚本名称。这个名称和文件名称无关,只是在任务管理中显示的名称。
  • +
  • script <string> 要运行的脚本内容。
  • +
  • config \ 运行配置项
      +
    • delay <number> 延迟执行的毫秒数,默认为0
    • +
    • loopTimes <number> 循环运行次数,默认为1
    • +
    • interval <number> 循环运行时两次运行之间的时间间隔,默认为0
    • +
    • path <Array> | <string> 指定脚本运行的目录。这个路径会用于require时寻找模块文件。
    • +
    +
  • +
+

在新线程中运行脚本script。返回一个ScriptExectuion对象。

+

engines.execScriptFile(path[, config])#

+
    +
  • path <string> 要运行的脚本路径。
  • +
  • config \ 运行配置项
      +
    • delay <number> 延迟执行的毫秒数,默认为0
    • +
    • loopTimes <number> 循环运行次数,默认为1
    • +
    • interval <number> 循环运行时两次运行之间的时间间隔,默认为0
    • +
    • path <Array> | <string> 指定脚本运行的目录。这个路径会用于require时寻找模块文件。
    • +
    +
  • +
+

在新线程中运行脚本文件path。返回一个ScriptExecution对象。

+

engines.execAutoFile(path[, config])#

+
    +
  • path <string> 要运行的录制文件路径。
  • +
  • config \ 运行配置项
      +
    • delay <number> 延迟执行的毫秒数,默认为0
    • +
    • loopTimes <number> 循环运行次数,默认为1
    • +
    • interval <number> 循环运行时两次运行之间的时间间隔,默认为0
    • +
    • path <Array> | <string> 指定脚本运行的目录。这个路径会用于require时寻找模块文件。
    • +
    +
  • +
+

在新线程中运行录制文件path。返回一个ScriptExecution对象。

+

engines.stopAll()#

+

停止所有正在运行的脚本。包括当前脚本自身。

+

engines.stopAllAndToast()#

+

停止所有正在运行的脚本并显示停止的脚本数量。包括当前脚本自身。

+

engines.myEngine()#

+

返回当前脚本的脚本引擎对象(ScriptEngine)

+

ScriptExecution#

+

执行脚本时返回的对象,可以通过他获取执行的引擎、配置、源码等。

+

ScriptExecution.getEngine()#

+

返回执行该脚本的脚本引擎对象(ScriptEngine)

+

ScriptExecution.getConfig()#

+

返回该脚本的运行配置(ScriptConfig)

+

ScriptExecution.getSource()#

+

返回该脚本的源码对象(ScriptSource)

+

ScriptEngine#

+

ScriptEngine.forceStop()#

+

停止脚本引擎的执行。

+

ScriptEngine.getTag(tagName)#

+
+

返回对应于tagName的附加在该脚本引擎上的额外信息。tagName包括:

+
    +
  • source 该脚本引擎当前正在执行的源码(ScriptSource)
  • +
  • execute_path 该脚本引擎当前执行的路径
  • +
+

停止脚本引擎的执行。

+

ScriptConfig#

+

脚本执行时的配置。

+

delay#

+

延迟执行的毫秒数

+

interval#

+

循环运行时两次运行之间的时间间隔

+

loopTimes#

+

循环运行次数

+

getPath()#

+

返回一个字符串数组表示脚本运行时模块寻找的路径。

+

ScriptSource#

+

脚本执行时的源码对象。可以是字符串源码、文件源码等。

+

如果该源码是文件脚本,则可以通过toString()得到该文件的路径。

+

getName()#

+

返回该源码的名称。

+

getEngineName()#

+

返回执行该源码的脚本引擎的名称。

+ + +

module (模块)#

+
Stability: 2 - Stable

Auto.js 有一个简单的模块加载系统。 在 Auto.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块)。

+

例子,假设有一个名为 foo.js 的文件:

+
const circle = require('./circle.js');
+console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`);
+

在第一行中,foo.js 加载了同一目录下的 circle.js 模块。

+

circle.js 文件的内容为:

+
const { PI } = Math;
+
+exports.area = (r) => PI * r ** 2;
+
+exports.circumference = (r) => 2 * PI * r;
+

circle.js 模块导出了 area() 和 circumference() 两个函数。 通过在特殊的 exports 对象上指定额外的属性,函数和对象可以被添加到模块的根部。

+

模块内的本地变量是私有的,因为模块被 Node.js 包装在一个函数中(详见模块包装器)。 在这个例子中,变量 PI 是 circle.js 私有的。

+

module.exports属性可以被赋予一个新的值(例如函数或对象)。

+

如下,bar.js 会用到 square 模块,square 导出一个构造函数:

+
const square = require('./square.js');
+const mySquare = square(2);
+console.log(`正方形的面积是 ${mySquare.area()}`);
+square 模块定义在 square.js 中:
+
+// 赋值给 `exports` 不会修改模块,必须使用 `module.exports`
+module.exports = function(width) {
+  return {
+    area: () => width ** 2
+  };
+};
+
+ + + +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/app.html b/app/src/main/assets/docs/app.html new file mode 100644 index 00000000..7cd468b3 --- /dev/null +++ b/app/src/main/assets/docs/app.html @@ -0,0 +1,165 @@ + + + + + App | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

App#

+

app模块提供一系列函数,用于与其他应用的交互。例如打开文件、拍照、发送邮件等。

+

同时提供了方便的基础函数startActivity和sendBroadcast,用他们可完成app模块没有内置的和其他应用的交互。

+

app.viewFile(path)#

+
+

用其他应用查看文件。

+

app.editFile(path)#

+
+

用其他应用编辑文件。

+

app.uninstall(packageName)#

+
+

卸载应用。

+

app.openUrl(url)#

+
+

用浏览器打开网站url。

+

app.takePhoto(path)#

+
+

调用相机应用拍照,完成后保存到路径path。

+

app.sendEmail(options)#

+
    +
  • options <Object> 发送邮件的参数。包括:
      +
    • email <string> | <Array> 收件人的邮件地址。如果有多个收件人,则用字符串数组表示
    • +
    • cc <string> | <Array> 抄送收件人的邮件地址。如果有多个抄送收件人,则用字符串数组表示
    • +
    • bcc <string> | <Array> 密送收件人的邮件地址。如果有多个密送收件人,则用字符串数组表示
    • +
    • subject <string> 邮件主题(标题)
    • +
    • text <string> 邮件正文
    • +
    • attachment <string> | <Array> 附件的路径。如果有多个附件,则用字符串数组表示
    • +
    +
  • +
+

根据选项options调用邮箱应用发送邮件。这些选项均是可选的。

+

app.intent(intent)#

+
    +
  • intent <Object> 一个表示Intent对象,其属性可以包括:
      +
    • action <string> 这个Intent的Action,比如"android.intent.action.SEND"
    • +
    • type <string> 这个Intent的MimeType,比如"text/plain"
    • +
    • data <string> 这个Intent的Data(Uri),可以是文件路径或者Url等。
    • +
    • category \ 这个Intent的Category的字符串数组。
    • +
    • packageName <string> 目标包名
    • +
    • className <string> 目标Activity或Service等组件的名称
    • +
    • extras <Object> 以键值对构成的这个Intent的Extras。
    • +
    +
  • +
+

返回用intent对象构造的android.content.Intent对象。

+

例如:

+
var i = app.intent({
+    action: "android.intent.action.VIEW",
+    type: "text/plain",
+    data: "file:///sdcard/1.txt",
+});
+

如果你看了一脸懵逼,请百度安卓Intent

+

app.startActivity(intent)#

+
    +
  • intent <Object> 与app.intent函数的参数一样的intent对象。
  • +
+

相当于context.startActivity(intent)。

+

app.sendBroadcast(intent)#

+
    +
  • intent <Object> 与app.intent函数的参数一样的intent对象。
  • +
+

相当于context.sendBroadcast(intent)。

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/assets/dnt_helper.js b/app/src/main/assets/docs/assets/dnt_helper.js new file mode 100644 index 00000000..9906db4f --- /dev/null +++ b/app/src/main/assets/docs/assets/dnt_helper.js @@ -0,0 +1,49 @@ +/** + * http://schalkneethling.github.io/blog/2015/11/06/respect-user-choice-do-not-track/ + * https://github.com/schalkneethling/dnt-helper/blob/master/js/dnt-helper.js + * + * Returns true or false based on whether doNotTack is enabled. It also takes into account the + * anomalies, such as !bugzilla 887703, which effect versions of Fx 31 and lower. It also handles + * IE versions on Windows 7, 8 and 8.1, where the DNT implementation does not honor the spec. + * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1217896 for more details + * @params {string} [dnt] - An optional mock doNotTrack string to ease unit testing. + * @params {string} [userAgent] - An optional mock userAgent string to ease unit testing. + * @returns {boolean} true if enabled else false + */ +function _dntEnabled(dnt, userAgent) { + + 'use strict'; + + // for old version of IE we need to use the msDoNotTrack property of navigator + // on newer versions, and newer platforms, this is doNotTrack but, on the window object + // Safari also exposes the property on the window object. + var dntStatus = dnt || navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack; + var ua = userAgent || navigator.userAgent; + + // List of Windows versions known to not implement DNT according to the standard. + var anomalousWinVersions = ['Windows NT 6.1', 'Windows NT 6.2', 'Windows NT 6.3']; + + var fxMatch = ua.match(/Firefox\/(\d+)/); + var ieRegEx = /MSIE|Trident/i; + var isIE = ieRegEx.test(ua); + // Matches from Windows up to the first occurrence of ; un-greedily + // http://www.regexr.com/3c2el + var platform = ua.match(/Windows.+?(?=;)/g); + + // With old versions of IE, DNT did not exist so we simply return false; + if (isIE && typeof Array.prototype.indexOf !== 'function') { + return false; + } else if (fxMatch && parseInt(fxMatch[1], 10) < 32) { + // Can't say for sure if it is 1 or 0, due to Fx bug 887703 + dntStatus = 'Unspecified'; + } else if (isIE && platform && anomalousWinVersions.indexOf(platform.toString()) !== -1) { + // default is on, which does not honor the specification + dntStatus = 'Unspecified'; + } else { + // sets dntStatus to Disabled or Enabled based on the value returned by the browser. + // If dntStatus is undefined, it will be set to Unspecified + dntStatus = { '0': 'Disabled', '1': 'Enabled' }[dntStatus] || 'Unspecified'; + } + + return dntStatus === 'Enabled' ? true : false; +} diff --git a/app/src/main/assets/docs/assets/sh.css b/app/src/main/assets/docs/assets/sh.css new file mode 100644 index 00000000..234de111 --- /dev/null +++ b/app/src/main/assets/docs/assets/sh.css @@ -0,0 +1,25 @@ +.sh_sourceCode { + font-weight: normal; + font-style: normal; +} + +.sh_sourceCode .sh_symbol, +.sh_sourceCode .sh_cbracket { + color: #333; +} + +.sh_sourceCode .sh_keyword { + color: #338; +} + +.sh_sourceCode .sh_string, +.sh_sourceCode .sh_regexp, +.sh_sourceCode .sh_number, +.sh_sourceCode .sh_specialchar { + color: #E54305; +} + +.sh_sourceCode .sh_comment { + color: #666; + font-weight: lighter; +} diff --git a/app/src/main/assets/docs/assets/sh_javascript.min.js b/app/src/main/assets/docs/assets/sh_javascript.min.js new file mode 100644 index 00000000..d12482ce --- /dev/null +++ b/app/src/main/assets/docs/assets/sh_javascript.min.js @@ -0,0 +1 @@ +if(!this.sh_languages){this.sh_languages={}}sh_languages.javascript=[[[/\/\/\//g,"sh_comment",1],[/\/\//g,"sh_comment",7],[/\/\*\*/g,"sh_comment",8],[/\/\*/g,"sh_comment",9],[/\b(?:abstract|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|final|finally|for|function|goto|if|implements|in|instanceof|interface|native|new|null|private|protected|prototype|public|return|static|super|switch|synchronized|throw|throws|this|transient|true|try|typeof|var|volatile|while|with)\b/g,"sh_keyword",-1],[/(\+\+|--|\)|\])(\s*)(\/=?(?![*\/]))/g,["sh_symbol","sh_normal","sh_symbol"],-1],[/(0x[A-Fa-f0-9]+|(?:[\d]*\.)?[\d]+(?:[eE][+-]?[\d]+)?)(\s*)(\/(?![*\/]))/g,["sh_number","sh_normal","sh_symbol"],-1],[/([A-Za-z$_][A-Za-z0-9$_]*\s*)(\/=?(?![*\/]))/g,["sh_normal","sh_symbol"],-1],[/\/(?:\\.|[^*\\\/])(?:\\.|[^\\\/])*\/[gim]*/g,"sh_regexp",-1],[/\b[+-]?(?:(?:0x[A-Fa-f0-9]+)|(?:(?:[\d]*\.)?[\d]+(?:[eE][+-]?[\d]+)?))u?(?:(?:int(?:8|16|32|64))|L)?\b/g,"sh_number",-1],[/"/g,"sh_string",10],[/'/g,"sh_string",11],[/~|!|%|\^|\*|\(|\)|-|\+|=|\[|\]|\\|:|;|,|\.|\/|\?|&|<|>|\|/g,"sh_symbol",-1],[/\{|\}/g,"sh_cbracket",-1],[/\b(?:Math|Infinity|NaN|undefined|arguments)\b/g,"sh_predef_var",-1],[/\b(?:Array|Boolean|Date|Error|EvalError|Function|Number|Object|RangeError|ReferenceError|RegExp|String|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt)\b/g,"sh_predef_func",-1],[/(?:[A-Za-z]|_)[A-Za-z0-9_]*(?=[ \t]*\()/g,"sh_function",-1]],[[/$/g,null,-2],[/(?:?)|(?:?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",2,1],[//g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",6,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",6,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",3]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",3]],[[/-->/g,"sh_comment",-2],[/ + + \ No newline at end of file diff --git a/app/src/main/assets/docs/coordinates-based-automation.html b/app/src/main/assets/docs/coordinates-based-automation.html new file mode 100644 index 00000000..2692be6b --- /dev/null +++ b/app/src/main/assets/docs/coordinates-based-automation.html @@ -0,0 +1,267 @@ + + + + + Android7.0以上点按与手势模拟 | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

Android7.0以上点按与手势模拟#

+
Stability: 2 - Stable

本章节介绍了一些适用于Android7.0以上、不需要root权限、依赖于无障碍服务的点按与手势模拟的全局函数。

+

注意以下命令只有Android7.0及以上才有效

+

click(x, y)#

+
+

模拟点击坐标(x, y),并返回是否点击成功。只有在点击执行完成后脚本才继续执行。

+

一般而言,只有点击过程(大约150毫秒)中被其他事件中断(例如用户自行点击)才会点击失败。

+

使用该函数模拟连续点击时可能有点击速度过慢的问题,这时可以用[press][]函数代替。

+
+

可以在开发者选项中启用指针位置来查看坐标

+
+

longClick(x, y)#

+
+

模拟长按坐标(x, y), 并 返回是否成功。只有在长按执行完成(大约600毫秒)时脚本才会继续执行。

+

一般而言,只有长按过程中被其他事件中断(例如用户自行点击)才会长按失败。

+

press(x, y, duration)#

+
    +
  • x <number> 要按住的坐标的x值
  • +
  • y <number> 要按住的坐标的y值
  • +
  • duration <number> 按住时长,单位毫秒
  • +
+

模拟按住坐标(x, y), 并返回是否成功。只有按住操作执行完成时脚本才会继续执行。

+

如果按住时间过短,那么会被系统认为是点击;如果时长超过500毫秒,则认为是长按。

+

一般而言,只有按住过程中被其他事件中断才会操作失败。

+

swipe(x1, y1, x2, y2, duration)#

+
    +
  • x1 <number> 滑动的起始坐标的x值
  • +
  • y1 <number> 滑动的起始坐标的y值
  • +
  • x2 <number> 滑动的结束坐标的x值
  • +
  • y2 <number> 滑动的结束坐标的y值
  • +
  • duration <number> 滑动时长,单位毫秒
  • +
+

模拟从坐标(x1, y1)滑动到坐标(x2, y2),并返回是否成功。只有滑动操作执行完成时脚本才会继续执行。

+

一般而言,只有滑动过程中被其他事件中断才会滑动失败。

+

gesture(duration, [x1, y1], [x2, y2], ...)#

+
    +
  • duration <number> 手势的时长
  • +
  • [x, y] ... 手势滑动路径的一系列坐标
  • +
+

模拟手势操作。例如gesture(1000, [0, 0], [500, 500], [500, 1000])为模拟一个从(0, 0)到(500, 500)到(500, 100)的手势操作,时长为2秒。

+

gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)#

+

同时模拟多个手势。每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势;duration为手势执行时长;坐标为手势经过的点的坐标。其中delay参数可以省略,默认为0。

+

例如手指捏合:

+
gestures([0, 500, [800, 300], [500, 1000]],
+         [0, 500, [300, 1500], [500, 1000]]);
+

setScreenMetrics(width, height)#

+
    +
  • width <number> 屏幕宽度,单位像素
  • +
  • height <number> 屏幕高度,单位像素
  • +
+

设置脚本坐标点击所适合的屏幕宽高。如果脚本运行时,屏幕宽度不一致会自动放缩坐标。

+

例如在1920*1080的设备中,某个操作的代码为

+
setScreenMetrics(1080, 1920);
+click(800, 200);
+longClick(300, 500);
+

那么在其他设备上AutoJs会自动放缩坐标以便脚本仍然有效。

+

RootAutomator#

+
Stability: 2 - Stable

RootAutomator是一个使用root权限来模拟触摸的对象,用它可以完成触摸与多点触摸,并且这些动作的执行没有延迟。

+

注意以下命令需要root权限

+
var ra = new RootAutomator();
+

RootAutomator.tap(x, y[, id])#

+
    +
  • x <number> 横坐标
  • +
  • y <number> 纵坐标
  • +
  • id <number> 多点触摸id,可选,默认为1,可以通过setDefaultId指定。
  • +
+

点击位置(x, y)。其中id是一个整数值,用于区分多点触摸,不同的id表示不同的"手指",例如:

+
var ra = new RootAutomator();
+//让"手指1"点击位置(100, 100)
+ra.tap(100, 100, 1);
+//让"手指2"点击位置(200, 200);
+ra.tap(200, 200, 2);
+ra.exit();
+

如果不需要多点触摸,则不需要id这个参数。 +多点触摸通常用于手势或游戏操作,例如模拟双指捏合、双指上滑等。

+

RootAutomator.swipe(x1, x2, y1, y2[, duration, id])#

+
    +
  • x1 <number> 滑动起点横坐标
  • +
  • y1 <number> 滑动起点纵坐标
  • +
  • x2 <number> 滑动终点横坐标
  • +
  • y2 <number> 滑动终点纵坐标
  • +
  • duration <number> 滑动时长,单位毫秒,默认值为300
  • +
  • id <number> 多点触摸id,可选,默认为1
  • +
+

模拟一次从(x1, y1)到(x2, y2)的时间为duration毫秒的滑动。

+

RootAutomator.press(x, y, duration[, id])#

+
+

模拟按下位置(x, y),时长为duration毫秒。

+

使用该函数模拟连续点击时可能有点击速度过慢的问题,这时可以用[RootAutomator.press][]函数代替。

+

RootAutomator.longPress(x, y[\, id])#

+
+

模拟长按位置(x, y)。

+

以上为简单模拟触摸操作的函数。如果要模拟一些复杂的手势,需要更底层的函数。

+

RootAutomator.touchDown(x, y[\, id])#

+
+

模拟手指按下位置(x, y)。

+

RootAutomator.touchMove(x, y[\, id])#

+
+

模拟移动手指到位置(x, y)。

+

RootAutomator.touchUp([id])#

+
    +
  • id <number> 多点触摸id,可选,默认为1
  • +
+

模拟手指弹起。

+

使用root权限点击和滑动的简单命令#

+
Stability: 1 - Experimental

注意:本章节的函数在后续版本很可能有改动!请勿过分依赖本章节函数的副作用。推荐使用[RootAutomator][]代替本章节的触摸函数。

+

以下函数均需要root权限,可以实现任意位置的点击、滑动等。

+
    +
  • 这些函数通常首字母大写以表示其特殊的权限。
  • +
  • 这些函数均不返回任何值。
  • +
  • 并且,这些函数的执行是异步的、非阻塞的,在不同机型上所用的时间不同。脚本不会等待动作执行完成才继续执行。因此最好在每个函数之后加上适当的sleep来达到期望的效果。
  • +
+

例如:

+
Tap(100, 100);
+sleep(500);
+

注意,动作的执行可能无法被停止,例如:

+
for(var i = 0; i < 100; i++){
+  Tap(100, 100);
+}
+

这段代码执行后可能会出现在任务管理中停止脚本后点击仍然继续的情况。 +因此,强烈建议在每个动作后加上延时:

+
for(var i = 0; i < 100; i++){
+  Tap(100, 100);
+  sleep(500);
+}
+

Tap(x, y)#

+
+

点击位置(x, y), 您可以通过"开发者选项"开启指针位置来确定点击坐标。

+

Swipe(x1, y1, x2, y2, [duration])#

+
    +
  • x1, y1 <number> 滑动起点的坐标
  • +
  • x2, y2 <number> 滑动终点的坐标
  • +
  • duration <number> 滑动动作所用的时间
  • +
+

滑动。从(x1, y1)位置滑动到(x2, y2)位置。

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/documentation.html b/app/src/main/assets/docs/documentation.html new file mode 100644 index 00000000..9c6e28e7 --- /dev/null +++ b/app/src/main/assets/docs/documentation.html @@ -0,0 +1,139 @@ + + + + + About this Documentation | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

About this Documentation#

+ +

The goal of this documentation is to comprehensively explain the Node.js +API, both from a reference as well as a conceptual point of view. Each +section describes a built-in module or high-level concept.

+

Where appropriate, property types, method arguments, and the arguments +provided to event handlers are detailed in a list underneath the topic +heading.

+

Every .html document has a corresponding .json document presenting +the same information in a structured manner. This feature is +experimental, and added for the benefit of IDEs and other utilities that +wish to do programmatic things with the documentation.

+

Every .html and .json file is generated based on the corresponding +.md file in the doc/api/ folder in Node.js's source tree. The +documentation is generated using the tools/doc/generate.js program. +The HTML template is located at doc/template.html.

+

If errors are found in this documentation, please submit an issue +or see the contributing guide for directions on how to submit a patch.

+

Stability Index#

+ +

Throughout the documentation are indications of a section's +stability. The Node.js API is still somewhat changing, and as it +matures, certain parts are more reliable than others. Some are so +proven, and so relied upon, that they are unlikely to ever change at +all. Others are brand new and experimental, or known to be hazardous +and in the process of being redesigned.

+

The stability indices are as follows:

+
Stability: 0 - Deprecated This feature is known to be problematic, and changes may be planned. Do not rely on it. Use of the feature may cause warnings to be emitted. Backwards compatibility across major versions should not be expected.
Stability: 1 - Experimental This feature is still under active development and subject to non-backwards compatible changes, or even removal, in any future version. Use of the feature is not recommended in production environments. Experimental features are not subject to the Node.js Semantic Versioning model.

Note: Caution must be used when making use of Experimental features, +particularly within modules that may be used as dependencies (or dependencies +of dependencies) within a Node.js application. End users may not be aware that +experimental features are being used, and therefore may experience unexpected +failures or behavioral changes when changes occur. To help avoid such surprises, +Experimental features may require a command-line flag to explicitly enable +them, or may cause a process warning to be emitted. By default, such warnings +are printed to stderr and may be handled by attaching a listener to the +process.on('warning') event.

+
Stability: 2 - Stable The API has proven satisfactory. Compatibility with the npm ecosystem is a high priority, and will not be broken unless absolutely necessary.

JSON Output#

+
Stability: 1 - Experimental

Every HTML file in the markdown has a corresponding JSON file with the +same data.

+

This feature was added in Node.js v0.6.12. It is experimental.

+

Syscalls and man pages#

+

System calls like open(2) and read(2) define the interface between user programs +and the underlying operating system. Node functions which simply wrap a syscall, +like fs.open(), will document that. The docs link to the corresponding man +pages (short for manual pages) which describe how the syscalls work.

+

Note: some syscalls, like lchown(2), are BSD-specific. That means, for +example, that fs.lchown() only works on macOS and other BSD-derived systems, +and is not available on Linux.

+

Most Unix syscalls have Windows equivalents, but behavior may differ on Windows +relative to Linux and macOS. For an example of the subtle ways in which it's +sometimes impossible to replace Unix syscall semantics on Windows, see Node +issue 4760.

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/engines.html b/app/src/main/assets/docs/engines.html new file mode 100644 index 00000000..1527834b --- /dev/null +++ b/app/src/main/assets/docs/engines.html @@ -0,0 +1,196 @@ + + + + + Engines | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

Engines#

+
Stability: 2 - Stable

engines模块包含了一些与脚本引擎有关的函数,包括运行其他脚本,关闭脚本等。

+

engines.execScript(name, script[, config])#

+
    +
  • name <string> 要运行的脚本名称。这个名称和文件名称无关,只是在任务管理中显示的名称。
  • +
  • script <string> 要运行的脚本内容。
  • +
  • config \ 运行配置项
      +
    • delay <number> 延迟执行的毫秒数,默认为0
    • +
    • loopTimes <number> 循环运行次数,默认为1
    • +
    • interval <number> 循环运行时两次运行之间的时间间隔,默认为0
    • +
    • path <Array> | <string> 指定脚本运行的目录。这个路径会用于require时寻找模块文件。
    • +
    +
  • +
+

在新线程中运行脚本script。返回一个ScriptExectuion对象。

+

engines.execScriptFile(path[, config])#

+
    +
  • path <string> 要运行的脚本路径。
  • +
  • config \ 运行配置项
      +
    • delay <number> 延迟执行的毫秒数,默认为0
    • +
    • loopTimes <number> 循环运行次数,默认为1
    • +
    • interval <number> 循环运行时两次运行之间的时间间隔,默认为0
    • +
    • path <Array> | <string> 指定脚本运行的目录。这个路径会用于require时寻找模块文件。
    • +
    +
  • +
+

在新线程中运行脚本文件path。返回一个ScriptExecution对象。

+

engines.execAutoFile(path[, config])#

+
    +
  • path <string> 要运行的录制文件路径。
  • +
  • config \ 运行配置项
      +
    • delay <number> 延迟执行的毫秒数,默认为0
    • +
    • loopTimes <number> 循环运行次数,默认为1
    • +
    • interval <number> 循环运行时两次运行之间的时间间隔,默认为0
    • +
    • path <Array> | <string> 指定脚本运行的目录。这个路径会用于require时寻找模块文件。
    • +
    +
  • +
+

在新线程中运行录制文件path。返回一个ScriptExecution对象。

+

engines.stopAll()#

+

停止所有正在运行的脚本。包括当前脚本自身。

+

engines.stopAllAndToast()#

+

停止所有正在运行的脚本并显示停止的脚本数量。包括当前脚本自身。

+

engines.myEngine()#

+

返回当前脚本的脚本引擎对象(ScriptEngine)

+

ScriptExecution#

+

执行脚本时返回的对象,可以通过他获取执行的引擎、配置、源码等。

+

ScriptExecution.getEngine()#

+

返回执行该脚本的脚本引擎对象(ScriptEngine)

+

ScriptExecution.getConfig()#

+

返回该脚本的运行配置(ScriptConfig)

+

ScriptExecution.getSource()#

+

返回该脚本的源码对象(ScriptSource)

+

ScriptEngine#

+

ScriptEngine.forceStop()#

+

停止脚本引擎的执行。

+

ScriptEngine.getTag(tagName)#

+
+

返回对应于tagName的附加在该脚本引擎上的额外信息。tagName包括:

+
    +
  • source 该脚本引擎当前正在执行的源码(ScriptSource)
  • +
  • execute_path 该脚本引擎当前执行的路径
  • +
+

停止脚本引擎的执行。

+

ScriptConfig#

+

脚本执行时的配置。

+

delay#

+

延迟执行的毫秒数

+

interval#

+

循环运行时两次运行之间的时间间隔

+

loopTimes#

+

循环运行次数

+

getPath()#

+

返回一个字符串数组表示脚本运行时模块寻找的路径。

+

ScriptSource#

+

脚本执行时的源码对象。可以是字符串源码、文件源码等。

+

如果该源码是文件脚本,则可以通过toString()得到该文件的路径。

+

getName()#

+

返回该源码的名称。

+

getEngineName()#

+

返回执行该源码的脚本引擎的名称。

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/events.html b/app/src/main/assets/docs/events.html new file mode 100644 index 00000000..8b783f06 --- /dev/null +++ b/app/src/main/assets/docs/events.html @@ -0,0 +1,499 @@ + + + + + Events | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

Events#

+
Stability: 2 - Stable

events模块提供了监听手机通知、按键、触摸的接口。您可以用他配合自动操作函数完成自动化工作。

+

events本身是一个EventEmiiter, 但内置了一些事件、包括按键事件、通知事件、Toast事件等。

+

events.emitter()#

+

返回一个新的[EventEmitter][]。这个EventEmitter没有内置任何事件。

+

events.observeKey()#

+

启用按键监听,例如音量键、Home键。此函数使用无障碍服务实现,因此此函数会调用auto()确保无障碍服务启用。

+

只有这个函数成功执行后, [onKeyDown][], [onKeyUp][]等按键事件的监听才有效。

+

该函数在安卓4.3以上才能使用。

+

events.onKeyDown(keyName, listener)#

+
+

注册一个按键监听函数,当有keyName对应的按键被按下会调用该函数。可用的按键名称参见[Keys][]。

+

例如:

+
//启用按键监听
+events.observeKey();
+//监听音量上键按下
+events.onKeyDown("volume_up", function(event){
+    toast("音量上键被按下了");
+});
+//监听菜单键按下
+events.onKeyDown("menu", function(event){
+    toast("菜单键被按下了");
+    exit();
+});
+

events.onKeyUp(keyName, listener)#

+
+

注册一个按键监听函数,当有keyName对应的按键弹起会调用该函数。可用的按键名称参见Keys

+

一次完整的按键动作包括了按键按下和弹起。按下事件会在手指按下一个按键的"瞬间"触发, 弹起事件则在手指放开这个按键时触发。

+

例如:

+
//启用按键监听
+events.observeKey();
+//监听音量下键弹起
+events.onKeyDown("volume_down", function(event){
+    toast("音量上键弹起");
+});
+//监听Home键弹起
+events.onKeyDown("home", function(event){
+    toast("Home键弹起");
+    exit();
+});
+

events.onceKeyDown(keyName, listener)#

+
+

注册一个按键监听函数,当有keyName对应的按键被按下时会调用该函数,之后会注销该按键监听器。

+

也就是listener只有在onceKeyDown调用后的第一次按键事件被调用一次。

+

events.onceKeyUp(keyName, listener)#

+
+

注册一个按键监听函数,当有keyName对应的按键弹起时会调用该函数,之后会注销该按键监听器。

+

也就是listener只有在onceKeyUp调用后的第一次按键事件被调用一次。

+

events.removeAllKeyDownListeners(keyName)#

+
+

删除该按键的KeyDown(按下)事件的所有监听。

+

events.removeAllKeyUpListeners(keyName)#

+
+

删除该按键的KeyUp(弹起)事件的所有监听。

+

events.observeTouch()#

+

启用屏幕触摸监听。(需要root权限)

+

只有这个函数被成功执行后, 触摸事件的监听才有效。

+

没有root权限调用该函数则什么也不会发生。(注意: 这个行为未来可能会更改为抛出异常)

+

events.setTouchEventTimeout(timeout)#

+
    +
  • timeout <number> 两个触摸事件的最小间隔。单位毫秒。默认为10毫秒。如果number小于0,视为0处理。
  • +
+

设置两个触摸事件分发的最小时间间隔。

+

例如间隔为10毫秒的话,前一个触摸事件发生并被注册的监听器处理后,至少要过10毫秒才能分发和处理下一个触摸事件,这10毫秒之间的触摸将会被忽略。

+

建议在满足需要的情况下尽量提高这个间隔。一个简单滑动动作可能会连续触发上百个触摸事件,如果timeout设置过低可能造成事件拥堵。强烈建议不要设置timeout为0。

+

events.getTouchEventTimeout()#

+

返回触摸事件的最小时间间隔。

+

events.onTouch(listener)#

+
    +
  • listener <Function> 参数为[Point][]的函数
  • +
+

注册一个触摸监听函数。相当于on("touch", listener)

+

例如:

+
//启用触摸监听
+events.observeTouch();
+//注册触摸监听器
+events.onTouch(function(p){
+    //触摸事件发生时, 打印出触摸的点的坐标
+    log(p.x + ", " + p.y);
+});
+

events.removeAllTouchListeners()#

+

删除所有事件监听函数。

+

事件: 'key'#

+
    +
  • keyCode <number> 键值
  • +
  • event <KeyEvent> 事件
  • +
+

当有按键被按下或弹起时会触发该事件。 +例如:

+
auto();
+events.observeKey();
+events.on("key", function(keyCode, event){
+    //处理按键事件
+});
+

其中监听器的参数KeyCode包括:

+
    +
  • KeyEvent.KEYCODE_HOME 主页键
  • +
  • KeyEvent.KEYCODE_BACK 返回键
  • +
  • KeyEvent.KEYCODE_MENU 菜单键
  • +
  • KeyEvent.KEYCODE_VOLUMEUP 音量上键
  • +
  • KeyEvent.KEYCODE_VOLUMEDOWN 音量下键
  • +
+

事件: 'key_down'#

+
    +
  • keyCode <number> 键值
  • +
  • event <KeyEvent> 事件
  • +
+

当有按键被按下时会触发该事件。

+
auto();
+events.observeKey();
+events.on("key_down", function(keyCode, event){
+    //处理按键按下事件
+});
+

事件: 'key_up'#

+
    +
  • keyCode <number> 键值
  • +
  • event <KeyEvent> 事件
  • +
+

当有按键弹起时会触发该事件。

+
auto();
+events.observeKey();
+events.on("key_up", function(keyCode, event){
+    //处理按键弹起事件
+});
+

obverseNotification()#

+

开启通知(包括Toast)监听。

+

通知与Toast监听依赖于无障碍服务,因此这个函数会调用auto()来确保无障碍服务启用。

+

例如:

+
events.obverseNotification();
+events.onNotification(function(notification){
+    log(notification.getText());
+});
+events.onToast(function(toast){
+    log(toast.getText());
+});
+

事件: 'toast'#

+
    +
  • toast <Object>
      +
    • getText() 获取Toast的文本内容
    • +
    • getPackageName() 获取发出Toast的应用包名
    • +
    +
  • +
+

当有应用发出toast(气泡消息)时会触发该事件。但Auto.js软件本身的toast除外。 +例如,要记录发出所有toast的应用:

+
events.obverseNotification();
+events.onToast(function(toast){
+    log("Toast内容: " + toast.getText() + " 包名: " + toast.getPackageName());
+});
+

事件: 'notification'#

+
+

当有应用发出通知时会触发该事件。

+

例如:

+
events.observeNotification();
+events.on("notification", function(notification){
+    log(notification);
+});
+

注意: 这是一个实验性功能。实测只有某些情况下的通知才能被正确捕捉。

+

EventEmitter#

+
Stability: 2 - Stable

EventEmitter.defaultMaxListeners#

+

每个事件默认可以注册最多 10 个监听器。 单个 EventEmitter 实例的限制可以使用 emitter.setMaxListeners(n) 方法改变。 所有 EventEmitter 实例的默认值可以使用 EventEmitter.defaultMaxListeners 属性改变。

+

设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有 EventEmitter 实例,包括之前创建的。 因而,调用 emitter.setMaxListeners(n) 优先于 EventEmitter.defaultMaxListeners。

+

注意,与Node.js不同,这是一个硬性限制。 EventEmitter 实例不允许添加更多的监听器,监听器超过最大数量时会抛出TooManyListenersException。

+
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
+emitter.once('event', () => {
+  // 做些操作
+  emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
+});
+

EventEmitter.addListener(eventName, listener)#

+
+

emitter.on(eventName, listener) 的别名。

+

EventEmitter.emit(eventName[, ...args])#

+
    +
  • eventName <any>
  • +
  • args <any>
  • +
+

按监听器的注册顺序,同步地调用每个注册到名为 eventName 事件的监听器,并传入提供的参数。

+

如果事件有监听器,则返回 true ,否则返回 false。

+

EventEmitter.eventNames()#

+

返回一个列出触发器已注册监听器的事件的数组。 数组中的值为字符串或符号。

+
const myEE = events.emitter();
+myEE.on('foo', () => {});
+myEE.on('bar', () => {});
+
+const sym = Symbol('symbol');
+myEE.on(sym, () => {});
+
+console.log(myEE.eventNames());
+// 打印: [ 'foo', 'bar', Symbol(symbol) ]
+

EventEmitter.getMaxListeners()#

+

返回 EventEmitter 当前的最大监听器限制值,该值可以通过 emitter.setMaxListeners(n) 设置或默认为 EventEmitter.defaultMaxListeners。

+

EventEmitter.listenerCount(eventName)#

+
    +
  • eventName <string> 正在被监听的事件名
  • +
+

返回正在监听名为 eventName 的事件的监听器的数量。

+

EventEmitter.listeners(eventName)#

+
+

返回名为 eventName 的事件的监听器数组的副本。

+
server.on('connection', (stream) => {
+  console.log('someone connected!');
+});
+console.log(util.inspect(server.listeners('connection')));
+// 打印: [ [Function] ]
+

EventEmitter.on(eventName, listener)#

+
    +
  • eventName <any> 事件名
  • +
  • listener <Function> 回调函数
  • +
+

添加 listener 函数到名为 eventName 的事件的监听器数组的末尾。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。

+
server.on('connection', (stream) => {
+  console.log('有连接!');
+});
+

返回一个 EventEmitter 引用,可以链式调用。

+

默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependListener() 方法可用于将事件监听器添加到监听器数组的开头。

+
const myEE = events.emitter();
+myEE.on('foo', () => console.log('a'));
+myEE.prependListener('foo', () => console.log('b'));
+myEE.emit('foo');
+// 打印:
+//   b
+//   a
+

EventEmitter.once(eventName, listener)#

+
    +
  • eventName <any> 事件名
  • +
  • listener <Function> 回调函数
  • +
+

添加一个单次 listener 函数到名为 eventName 的事件。 下次触发 eventName 事件时,监听器会被移除,然后调用。

+
server.once('connection', (stream) => {
+  console.log('首次调用!');
+});
+

返回一个 EventEmitter 引用,可以链式调用。

+

默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependOnceListener() 方法可用于将事件监听器添加到监听器数组的开头。

+
const myEE = events.emitter();
+myEE.once('foo', () => console.log('a'));
+myEE.prependOnceListener('foo', () => console.log('b'));
+myEE.emit('foo');
+// 打印:
+//   b
+//   a
+

EventEmitter.prependListener(eventName, listener)#

+
    +
  • eventName <any> 事件名
  • +
  • listener <Function> 回调函数
  • +
+

添加 listener 函数到名为 eventName 的事件的监听器数组的开头。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。

+
server.prependListener('connection', (stream) => {
+  console.log('有连接!');
+});
+

返回一个 EventEmitter 引用,可以链式调用。

+

EventEmitter.prependOnceListener(eventName, listener)#

+
    +
  • eventName <any> 事件名
  • +
  • listener <Function> 回调函数
  • +
+

添加一个单次 listener 函数到名为 eventName 的事件的监听器数组的开头。 下次触发 eventName 事件时,监听器会被移除,然后调用。

+
server.prependOnceListener('connection', (stream) => {
+  console.log('首次调用!');
+});
+

返回一个 EventEmitter 引用,可以链式调用。

+

EventEmitter.removeAllListeners([eventName])#

+
    +
  • eventName <any>
  • +
+

移除全部或指定 eventName 的监听器。

+

注意,在代码中移除其他地方添加的监听器是一个不好的做法,尤其是当 EventEmitter 实例是其他组件或模块创建的。

+

返回一个 EventEmitter 引用,可以链式调用。

+

EventEmitter.removeListener(eventName, listener)#

+
+

从名为 eventName 的事件的监听器数组中移除指定的 listener。

+
const callback = (stream) => {
+  console.log('有连接!');
+};
+server.on('connection', callback);
+// ...
+server.removeListener('connection', callback);
+

removeListener 最多只会从监听器数组里移除一个监听器实例。 如果任何单一的监听器被多次添加到指定 eventName 的监听器数组中,则必须多次调用 removeListener 才能移除每个实例。

+

注意,一旦一个事件被触发,所有绑定到它的监听器都会按顺序依次触发。 这意味着,在事件触发后、最后一个监听器完成执行前,任何 removeListener() 或 removeAllListeners() 调用都不会从 emit() 中移除它们。 随后的事件会像预期的那样发生。

+
const myEmitter = events.emitter();
+
+const callbackA = () => {
+  console.log('A');
+  myEmitter.removeListener('event', callbackB);
+};
+
+const callbackB = () => {
+  console.log('B');
+};
+
+myEmitter.on('event', callbackA);
+
+myEmitter.on('event', callbackB);
+
+// callbackA 移除了监听器 callbackB,但它依然会被调用。
+// 触发是内部的监听器数组为 [callbackA, callbackB]
+myEmitter.emit('event');
+// 打印:
+//   A
+//   B
+
+// callbackB 被移除了。
+// 内部监听器数组为 [callbackA]
+myEmitter.emit('event');
+// 打印:
+//   A
+

因为监听器是使用内部数组进行管理的,所以调用它会改变在监听器被移除后注册的任何监听器的位置索引。 虽然这不会影响监听器的调用顺序,但意味着由 emitter.listeners() 方法返回的监听器数组副本需要被重新创建。

+

返回一个 EventEmitter 引用,可以链式调用。

+

EventEmitter.setMaxListeners(n)#

+
+

默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 此限制有助于寻找内存泄露。 但是,并不是所有的事件都要被限为 10 个。 emitter.setMaxListeners() 方法允许修改指定的 EventEmitter 实例的限制。 值设为 Infinity(或 0)表明不限制监听器的数量。

+

返回一个 EventEmitter 引用,可以链式调用。

+

KeyEvent#

+
Stability: 2 - Stable

KeyEvent.getAction()#

+

返回事件的动作。包括:

+
    +
  • KeyEvent.ACTION_DOWN 按下事件
  • +
  • KeyEvent.ACTION_UP 弹起事件
  • +
+

KeyEvent.getKeyCode()#

+

返回按键的键值。包括:

+
    +
  • KeyEvent.KEYCODE_HOME 主页键
  • +
  • KeyEvent.KEYCODE_BACK 返回键
  • +
  • KeyEvent.KEYCODE_MENU 菜单键
  • +
  • KeyEvent.KEYCODE_VOLUME_UP 音量上键
  • +
  • KeyEvent.KEYCODE_VOLUME_DOWN 音量下键
  • +
+

KeyEvent.getEventTime()#

+

返回事件发生的时间戳。返回值的类型是number。

+

KeyEvent.getDownTime()#

+

返回最近一次按下事件的时间戳。如果本身是按下事件,则与getEventTime()相同。

+

KeyEvent.keyCodeToString(keyCode)#

+

把键值转换为字符串。例如KEYCODE_HOME转换为"KEYCODE_HOME"。

+

Keys#

+
Stability: 2 - Stable

按键事件中所有可用的按键名称为:

+
    +
  • volume_up 音量上键
  • +
  • volume_down 音量下键
  • +
  • home 主屏幕键
  • +
  • back 返回键
  • +
  • menu 菜单键
  • +
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/files.html b/app/src/main/assets/docs/files.html new file mode 100644 index 00000000..97d8d9a3 --- /dev/null +++ b/app/src/main/assets/docs/files.html @@ -0,0 +1,297 @@ + + + + + Files | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

Files#

+
Stability: 2 - Stable

files模块提供了一些常见的文件处理,包括文件读写、移动、复制、删掉等。

+

files.isFile(path)#

+
+

返回路径path是否是文件。

+

files.isDir(path)#

+
+

返回路径path是否是文件夹。

+

files.isEmptyDir(path)#

+
+

返回文件夹path是否为空文件夹。如果该路径并非文件夹,则直接返回false。

+

files.join(parent, child)#

+
+

连接两个路径并返回,例如files.join("/sdcard/", "1.txt")返回"/sdcard/1.txt"。

+

files.create(path)#

+
+

创建一个文件并返回是否创建成功。

+

files.createIfNotExists(path)#

+
+

创建一个文件并返回是否创建成功。

+

files.exists(path)#

+
+

返回在路径path处的文件是否存在。

+

files.ensureDir(path)#

+
+

确保路径path所在的文件夹存在。

+

例如对于路径"/sdcard/Download/ABC/1.txt",如果/Download/文件夹不存在,则会先创建Download,再创建ABC文件夹。

+

files.read(path[, encoding = "utf-8"])#

+
+

读取文件path的所有内容并返回。

+

files.write(path, text[, encoding = "utf-8"])#

+
+

把text写入到文件path中。如果文件存在则覆盖,不存在则创建。

+

files.copy(fromPath, toPath)#

+
    +
  • fromPath <string> 要复制的原文件路径
  • +
  • toPath <string> 复制到的文件路径
  • +
+

复制文件。例如files.copy("/sdcard/1.txt", "/sdcard/Download/1.txt")

+

files.move(fromPath, toPath)#

+
    +
  • fromPath <string> 要移动的原文件路径
  • +
  • toPath <string> 移动到的文件路径
  • +
+

移动文件,返回是否移动成功。例如files.move("/sdcard/1.txt", "/sdcard/Download/1.txt")会把1.txt文件从sd卡根目录移动到Download文件夹。

+

files.rename(path, newName)#

+
    +
  • path <string> 要重命名的原文件路径
  • +
  • newName <string> 要重命名的新文件名
  • +
+

重命名文件,并返回是否重命名成功。例如files.rename("/sdcard/1.txt", "2.txt")

+

files.renameWithoutExtension(path, newName)#

+
    +
  • path <string> 要重命名的原文件路径
  • +
  • newName <string> 要重命名的新文件名
  • +
+

重命名文件,不包含拓展名,并返回是否重命名成功。例如files.rename("/sdcard/1.txt", "2")会把1.txt重命名为2.txt。

+

files.getName(path)#

+
+

返回文件的文件名。例如files.getName("/sdcard/1.txt")返回"1.txt"。

+

files.getNameWithoutExtension(path)#

+
+

返回不含拓展名的文件的文件名。例如files.getName("/sdcard/1.txt")返回"1"。

+

files.getExtension(path)#

+
+

返回文件的拓展名。例如files.getExtension("/sdcard/1.txt")返回"txt"。

+

files.remove(path)#

+
+

删除文件或空文件夹,返回是否删除成功。

+

files.removeDir(path)#

+
+

删除文件夹,如果文件夹不为空,则删除该文件夹的所有内容再删除该文件夹,返回是否全部删除成功。

+

files.getSdcardPath()#

+

返回SD卡路径。所谓SD卡,即外部存储器。

+

files.listDir(path[, filter])#

+
    +
  • path <string> 路径
  • +
  • filter <Function> 过滤函数,可选。接收一个String参数(文件名),返回一个Boolean值。
  • +
+

列出文件夹path下的满足条件的文件和文件夹的名称的数组。如果不加filter参数,则返回所有文件和文件夹。

+

例如,获取sdcard目录下的txt文件为

+
var txtFiles = files.listDir("/sdcard/", function(name){
+    return name.endsWith(".txt") && files.isFile("/sdcard/" + name);
+});
+

open(path[, mode = "r", encoding = "utf-8", bufferSize = 8192])#

+
    +
  • path <string> 文件路径,例如"/sdcard/1.txt"。
  • +
  • mode <string> 文件打开模式,包括:
      +
    • "r": 只读模式。该模式下只能对文件执行文本读取操作。
    • +
    • "w": 只写模式。该模式下只能对文件执行文本覆盖写入操作。
    • +
    • "a": 附加模式。该模式下将会把写入的文本附加到文件末尾。
      目前暂不支持二进制模式,随机读写模式。
    • +
    +
  • +
  • encoding <string> 字符编码。
  • +
  • bufferSize <Number> 文件读写的缓冲区大小。
  • +
+

打开一个文件。根据打开模式返回不同的文件对象。包括:

+
    +
  • "r": 返回一个ReadableTextFile对象。
  • +
  • "w", "a": 返回一个WritableTextFile对象。
  • +
+

对于"w"模式,如果文件并不存在,则会创建一个,已存在则会清空该文件内容;其他模式文件不存在会抛出FileNotFoundException。

+

ReadableTextFile#

+

可读文件对象。

+

ReadableTextFile.read()#

+

返回该文件剩余的所有内容的字符串。

+

ReadableTextFile.read(maxCount)#

+
    +
  • maxCount <Number> 最大读取的字符数量
  • +
+

读取该文件接下来最长为maxCount的字符串并返回。即使文件剩余内容不足maxCount也不会出错。

+

ReadableTextFile.readline()#

+

读取一行并返回(不包含换行符)。

+

ReadableTextFile.readlines()#

+

读取剩余的所有行,并返回它们按顺序组成的字符串数组。

+

close()#

+

关闭该文件。

+

打开一个文件不再使用时务必关闭

+

PWritableTextFile#

+

可写文件对象。

+

PWritableTextFile.write(text)#

+
+

把文本内容text写入到文件中。

+

PWritableTextFile.writeline(line)#

+
+

把文本line写入到文件中并写入一个换行符。

+

PWritableTextFile.writelines(lines)#

+
+

把很多行写入到文件中....

+

PWritableTextFile.flush()#

+

把缓冲区内容输出到文件中。

+

PWritableTextFile.close()#

+

关闭文件。同时会被缓冲区内容输出到文件。

+

打开一个文件写入后,不再使用时务必关闭,否则文件可能会丢失

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/globals.html b/app/src/main/assets/docs/globals.html new file mode 100644 index 00000000..c3d4c28d --- /dev/null +++ b/app/src/main/assets/docs/globals.html @@ -0,0 +1,211 @@ + + + + + 全局变量与函数 | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

全局变量与函数#

+

全局变量和函数在所有模块中均可使用。 但以下变量的作用域只在模块内,详见 module文档:

+
    +
  • exports
  • +
  • module
  • +
  • require() +以下的对象是特定于 Auto.js 的。 有些内置对象是 JavaScript 语言本身的一部分,它们也是全局的。
  • +
+

一些模块中的函数为了使用方便也可以直接全局使用,这些函数在此不再赘述。例如timers模块的setInterval等函数。

+

sleep([n])#

+
+

暂停运行n毫秒的时间。1秒等于1000毫秒。

+

launchPackage(packageName)#

+
+

运行包名为packageName的应用主界面(Launcher)。例如,打开微信为:

+
launchPackage("com.tencent.mm");
+

如果存在多个应用包名相同的情况(如双开应用),如何处理取决于操作系统。在MIUI中会弹出多开应用的选择界面。

+

launchApp(appName)#

+
+

运行应用名称为appName的应用主界面。当有应用名称相同时只运行其中某一个。
例如,打开微信为:

+
launchApp("微信");
+

currentPackage()#

+

返回最近一次监测到的正在运行的应用的包名,一般可以认为就是当前正在运行的应用的包名。

+

currentActivity()#

+

返回最近一次监测到的正在运行的Activity的名称,一般可以认为就是当前正在运行的Activity的名称。

+

getPackageName(appName)#

+
+

获取应用的包名。例如getPackageName("QQ")为"com.tencent.mobileqq"。如果有相同名称的应用,只返回其中某一个的包名。如果不存在这个名称的应用,会返回null。

+

getAppName(packageName)#

+
+

返回对应包名的应用的名称。如果应用不存在,返回null。

+

openAppSetting(packageName)#

+
+

打开某个应用的应用详情页,也就是管理应用权限和可以停止其运行的页面。如果应用包名不存在,则返回false;否则返回true。

+

setClip(text)#

+
+

设置剪贴板内容。此剪贴板即系统剪贴板,在一般应用的输入框中"粘贴"既可使用。

+

getClip()#

+

返回系统剪贴板的内容。

+

toast(message)#

+
    +
  • message <string>> | <{Object> 要显示的信息
  • +
+

以气泡显示信息message几秒。(具体时间取决于安卓系统,一般都是2秒)

+

注意,信息的显示是"异步"执行的(不属于Looper循环),并且,不会等待信息消失程序才继续执行。如果在循环中执行该命令,可能出现脚本停止运行后仍然有不断的气泡信息出现的情况。 +例如:

+
for(var i = 0; i < 100; i++){
+  toast(i);
+}
+

运行这段程序以后,会很快执行完成,且不断弹出消息,在任务管理中关闭所有脚本也无法停止。 +要保证气泡消息才继续执行可以用:

+
for(var i = 0; i < 100; i++){
+  toast(i);
+  sleep(2000);
+}
+

或者修改toast函数:

+
var _toast_ = toast;
+toast = function(message){
+  _toast_(message);
+  sleep(2000);
+}
+for(var i = 0; i < 100; i++){
+  toast(i);
+  sleep(2000);
+}
+

toastLog(message)#

+
    +
  • message \ | \ 要显示的信息
  • +
+

相当于toast(message);log(message)。显示信息message并在控制台中输出。参见console.log。

+

waitForActivity(activity[, period = 200])#

+
    +
  • activity Activity名称
  • +
  • period 轮询等待间隔(毫秒)
  • +
+

等待指定的Activity出现,period为检查Activity的间隔。

+

waitForPackage(package[, period = 200])#

+
    +
  • package 包名
  • +
  • period 轮询等待间隔(毫秒)
  • +
+

等待指定的应用出现。例如waitForPackage("com.tencent.mm")为等待当前界面为微信。

+

exit()#

+

立即停止脚本运行。

+

random(min, max)#

+
    +
  • min <number> 随机数产生的区间下界
  • +
  • max <number> 随机数产生的区间上界
  • +
+

返回一个在[min...max]之间的随机数。例如random(0, 2)可能产生0, 1, 2.

+

random()#

+

返回在[0, 1)的随机浮点数。

+

context#

+

全局变量。一个android.content.Context对象。

+

注意该对象为ApplicationContext,因此不能用于界面、对话框等的创建。

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/images.html b/app/src/main/assets/docs/images.html new file mode 100644 index 00000000..af75e99c --- /dev/null +++ b/app/src/main/assets/docs/images.html @@ -0,0 +1,256 @@ + + + + + Images | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

Images#

+
Stability: 2 - Stable

images模块提供了一些手机设备中常见的图片处理函数,包括截图、读写图片、图片剪裁、找色、找图等。

+

requestScreenCapture([width, height])#

+
+

向系统申请屏幕截图权限,返回是否请求成功。

+

第一次使用该函数会弹出截图权限请求,建议选择“总是允许”。

+

这个函数只是申请截图权限,并不会真正执行截图,真正的截图函数是[captureScreen][]都调用一次。

+

该函数在截图脚本中只需执行一次,而无需每次调用[captureScreen][]都调用一次。

+

不指定参数时默认为屏幕宽高。指定参数时,并不会严格以width和height为截图宽度和高度,而是以和width, height接近的最适合的宽高为截图宽高。例如在1920*1080屏幕中requestScreenCapture(600, 1000)请求的截图的高度一般是540*960。

+

如果在第一次权限请求时选择"总是允许", 之后的脚本执行该函数通常耗时200毫秒以内(测试机型:小米6)。

+

建议在本软件界面运行该函数,在其他软件界面运行时容易出现一闪而过的黑屏。

+

如果要进行截图、找色的软件界面为横屏,则requestScreenCapture函数需要在横屏状态下执行,否则后续截图将会异常,调用findColor等函数时坐标变换会出现错误。

+

captureScreen()#

+

截取当前屏幕并返回一个[Image][]对象。

+

没有截图权限时执行该函数会抛出SecurityException。

+

该函数不会返回null,两次调用可能返回相同的Image对象。这是因为设备截图的更新需要一定的时间,短时间内(几十ms)连续调用则会返回同一张截图。

+

captureScreen(path)#

+
+

截取当前屏幕并以PNG格式保存到path中。如果文件不存在会被创建;文件存在会被覆盖。

+

该函数不会返回任何值。

+

images.pixel(image, x, y)#

+
    +
  • image <Image> 图片
  • +
  • x <number> 要获取的像素的横坐标。
  • +
  • y <y> 要获取的像素的纵坐标。
  • +
+

返回图片image在点(x, y)处的像素的ARGB值。

+

该值的格式为0xAARRGGBB,是一个"32位整数"(虽然JavaScript中并不区分整数类型和其他数值类型。

+

坐标系以图片左上角为原点。以图片左侧边为y轴,上侧边为x轴。

+

images.saveImage(image, path)#

+
    +
  • image <image> 图片
  • +
  • path <string> 路劲
  • +
+

把图片image以PNG格式保存到path中。如果文件不存在会被创建;文件存在会被覆盖。

+

images.findColor(image, color, options)#

+
    +
  • image <image> 图片
  • +
  • color <number> | <string> 要寻找的颜色的RGB值。如果是一个整数,则以0xRRGGBB的形式代表RGB值(A通道会被忽略);如果是字符串,则以"#RRGGBB"代表其RGB值。
  • +
  • options <Object> 选项
  • +
+

在图片中寻找颜色color。找到时返回找到的点[Point][],找不到时返回null。

+

选项包括:

+
    +
  • region <Array> 找色区域。是一个两个或四个元素的数组。(region[0], region[1])表示找色区域的左上角;region[2]*region[3]表示找色区域的宽高。如果只有region只有两个元素,则找色区域为(region[0], region[1])到屏幕右下角。如果不指定region选项,则找色区域为整张图片。
  • +
  • threads <number> 指定找色使用的线程数。不能超过16。最适合的线程数取决于设备。默认线程数为2。
  • +
  • algorithm <string> 指定颜色匹配算法。包括:
      +
    • "equal": 相等匹配,只有与给定颜色color完全相等时才匹配。
    • +
    • "diff": 差值匹配。与给定颜色的R、G、B差的绝对值之和小于threshold时匹配。
    • +
    • "rgb": rgb欧拉距离相似度。与给定颜色color的rgb欧拉距离小于等于threshold时匹配。
    • +
    • "rgb+": 加权rgb欧拉距离匹配(LAB Delta E)。
    • +
    • "hs": hs欧拉距离匹配。hs为HSV空间的色调值。
    • +
    +
  • +
  • threshold <number> 找色时颜色相似度的临界值,范围为0~255(越小越相似,0为颜色相等,255为任何颜色都能匹配)。默认为16。threshold和浮点数相似度(0.0~1.0)的换算为 similarity = (255 - threshold) / 255.
  • +
+

该函数也可以作为全局函数使用。

+

images.findColorInRegion(img, color, x, y[, width, height, threads, algorithm, threshold])#

+

相当于

+
images.findColor(img, color, {
+     region: [x, y, width, height],
+     algorithm: algorithm,
+     threshold: threshold,
+     threads: threads
+});
+

该函数也可以作为全局函数使用。

+

images.findColorEquals(img, color, x, y, width, height, threads)#

+

相当于

+
images.findColor(img, color, {
+   region: [x, y, width, height],
+   algorithm: "equal",
+   threads: threads
+});
+

该函数也可以作为全局函数使用。

+

images.detectsColor(image, color, x, y[, threshold = 16, algorithm = "rgb"])#

+
    +
  • image <Image> 图片
  • +
  • color <number> | <string> 要检测的颜色
  • +
  • x <number> 要检测的位置横坐标
  • +
  • y <number> 要检测的位置纵坐标
  • +
  • threshold <number> 颜色相似度临界值,默认为16
  • +
  • algorithm <string> 颜色匹配算法,默认为rgb欧式距离
  • +
+

返回图片image在位置(x, y)处是否匹配到颜色color。有关threshold和algorithm的信息,参考findColor函数。

+

colors#

+
Stability: 2 - Stable

colors是颜色处理的工具对象。包含一些常用方法,包括android.graphics.Color的所有方法以及toString方法。

+

colors.toString(color)#

+
+

返回颜色值的字符串,格式为 #AARRGGBB。

+

colors.red(color)#

+
+

返回颜色color的R通道的值,范围0~255.

+

colors.green(color)#

+
+

返回颜色color的G通道的值,范围0~255.

+

colors.blue(color)#

+
+

返回颜色color的B通道的值,范围0~255.

+

colors.alpha(color)#

+
+

返回颜色color的Alpha通道的值,范围0~255.

+

colors.rgb(red, green, blue)#

+
+

返回这些颜色通道构成的整数颜色值。Alpha通道将是255(不透明)。

+

colors.argb(alpha, red, green, blue)#

+
+

返回这些颜色通道构成的整数颜色值。

+

Image#

+

[captureScreen][] 返回的对象。

+

Image.getWidth()#

+

返回以像素为单位图片宽度。

+

Image.getHeight()#

+

返回以像素为单位的图片高度。

+

Point#

+

findColor返回的对象。

+

Point.x#

+

横坐标。

+

Point.y#

+

纵坐标。

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/index.html b/app/src/main/assets/docs/index.html new file mode 100644 index 00000000..60ad5d3e --- /dev/null +++ b/app/src/main/assets/docs/index.html @@ -0,0 +1,109 @@ + + + + + Index | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ +
+

目录

+ +
+ + +
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/keys.html b/app/src/main/assets/docs/keys.html new file mode 100644 index 00000000..a2c1f64b --- /dev/null +++ b/app/src/main/assets/docs/keys.html @@ -0,0 +1,263 @@ + + + + + Keys | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

Keys#

+

按键模拟部分提供了一些模拟物理按键的全局函数,包括Home、音量键、照相键等,有的函数依赖于无障碍服务,有的函数依赖于root权限。

+

back()#

+

模拟按下返回键。返回是否执行成功。 +此函数依赖于无障碍服务。

+

home()#

+

模拟按下Home键。返回是否执行成功。 +此函数依赖于无障碍服务。

+

powerDialog()#

+

弹出电源键菜单。返回是否执行成功。 +此函数依赖于无障碍服务。

+

notifications()#

+

弹出通知栏。返回是否执行成功。 +此函数依赖于无障碍服务。

+

quickSettings()#

+

显示快速设置(下拉通知栏到底)。返回是否执行成功。 +此函数依赖于无障碍服务。

+

recents()#

+

显示最近任务。返回是否执行成功。 +此函数依赖于无障碍服务。

+

splitScreen()#

+

分屏。返回是否执行成功。 +此函数依赖于无障碍服务。

+

Home()#

+

模拟按下Home键。 +此函数依赖于root权限。

+

Back()#

+

模拟按下返回键。 +此函数依赖于root权限。

+

Power()#

+

模拟按下电源键。 +此函数依赖于root权限。

+

Menu()#

+

模拟按下菜单键。 +此函数依赖于root权限。

+

VolumeUp()#

+

按下音量上键。 +此函数依赖于root权限。

+

VolumeDown()#

+

按键音量上键。 +此函数依赖于root权限。

+

Camera()#

+

模拟按下照相键。

+

Up()#

+

模拟按下物理按键上。 +此函数依赖于root权限。

+

Down()#

+

模拟按下物理按键下。 +此函数依赖于root权限。

+

Left()#

+

模拟按下物理按键左。 +此函数依赖于root权限。

+

Right()#

+

模拟按下物理按键右。 +此函数依赖于root权限。

+

OK()#

+

模拟按下物理按键确定。 +此函数依赖于root权限。

+

Text(text)#

+
    +
  • text <string> 要输入的文字,只能为英文或英文符号 +输入文字text。例如Text("aaa");
  • +
+

KeyCode(code)#

+
    +
  • code <number> | 要按下的按键的数字代码或名称。参见下表。 +模拟物理按键。例如KeyCode(29)KeyCode("KEYCODE_A")是按下A键。
  • +
+

附录: KeyCode对照表#

+

KeyCode KeyEvent Value

+
    +
  • KEYCODE_MENU 1
  • +
  • KEYCODE_SOFT_RIGHT 2
  • +
  • KEYCODE_HOME 3
  • +
  • KEYCODE_BACK 4
  • +
  • KEYCODE_CALL 5
  • +
  • KEYCODE_ENDCALL 6
  • +
  • KEYCODE_0 7
  • +
  • KEYCODE_1 8
  • +
  • KEYCODE_2 9
  • +
  • KEYCODE_3 10
  • +
  • KEYCODE_4 11
  • +
  • KEYCODE_5 12
  • +
  • KEYCODE_6 13
  • +
  • KEYCODE_7 14
  • +
  • KEYCODE_8 15
  • +
  • KEYCODE_9 16
  • +
  • KEYCODE_STAR 17
  • +
  • KEYCODE_POUND 18
  • +
  • KEYCODE_DPAD_UP 19
  • +
  • KEYCODE_DPAD_DOWN 20
  • +
  • KEYCODE_DPAD_LEFT 21
  • +
  • KEYCODE_DPAD_RIGHT 22
  • +
  • KEYCODE_DPAD_CENTER 23
  • +
  • KEYCODE_VOLUME_UP 24
  • +
  • KEYCODE_VOLUME_DOWN 25
  • +
  • KEYCODE_POWER 26
  • +
  • KEYCODE_CAMERA 27
  • +
  • KEYCODE_CLEAR 28
  • +
  • KEYCODE_A 29
  • +
  • KEYCODE_B 30
  • +
  • KEYCODE_C 31
  • +
  • KEYCODE_D 32
  • +
  • KEYCODE_E 33
  • +
  • KEYCODE_F 34
  • +
  • KEYCODE_G 35
  • +
  • KEYCODE_H 36
  • +
  • KEYCODE_I 37
  • +
  • KEYCODE_J 38
  • +
  • KEYCODE_K 39
  • +
  • KEYCODE_L 40
  • +
  • KEYCODE_M 41
  • +
  • KEYCODE_N 42
  • +
  • KEYCODE_O 43
  • +
  • KEYCODE_P 44
  • +
  • KEYCODE_Q 45
  • +
  • KEYCODE_R 46
  • +
  • KEYCODE_S 47
  • +
  • KEYCODE_T 48
  • +
  • KEYCODE_U 49
  • +
  • KEYCODE_V 50
  • +
  • KEYCODE_W 51
  • +
  • KEYCODE_X 52
  • +
  • KEYCODE_Y 53
  • +
  • KEYCODE_Z 54
  • +
  • KEYCODE_COMMA 55
  • +
  • KEYCODE_PERIOD 56
  • +
  • KEYCODE_ALT_LEFT 57
  • +
  • KEYCODE_ALT_RIGHT 58
  • +
  • KEYCODE_SHIFT_LEFT 59
  • +
  • KEYCODE_SHIFT_RIGHT 60
  • +
  • KEYCODE_TAB 61
  • +
  • KEYCODE_SPACE 62
  • +
  • KEYCODE_SYM 63
  • +
  • KEYCODE_EXPLORER 64
  • +
  • KEYCODE_ENVELOPE 65
  • +
  • KEYCODE_ENTER 66
  • +
  • KEYCODE_DEL 67
  • +
  • KEYCODE_GRAVE 68
  • +
  • KEYCODE_MINUS 69
  • +
  • KEYCODE_EQUALS 70
  • +
  • KEYCODE_LEFT_BRACKET 71
  • +
  • KEYCODE_RIGHT_BRACKET 72
  • +
  • KEYCODE_BACKSLASH 73
  • +
  • KEYCODE_SEMICOLON 74
  • +
  • KEYCODE_APOSTROPHE 75
  • +
  • KEYCODE_SLASH 76
  • +
  • KEYCODE_AT 77
  • +
  • KEYCODE_NUM 78
  • +
  • KEYCODE_HEADSETHOOK 79
  • +
  • KEYCODE_FOCUS 80
  • +
  • KEYCODE_PLUS 81
  • +
  • KEYCODE_MENU 82
  • +
  • KEYCODE_NOTIFICATION 83
  • +
  • KEYCODE_SEARCH 84
  • +
  • TAGLAST KEYCODE 85
  • +
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/modules.html b/app/src/main/assets/docs/modules.html new file mode 100644 index 00000000..9fa037c3 --- /dev/null +++ b/app/src/main/assets/docs/modules.html @@ -0,0 +1,109 @@ + + + + + module (模块) | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ +
+

目录

+ + +
+ +
+

module (模块)#

+
Stability: 2 - Stable

Auto.js 有一个简单的模块加载系统。 在 Auto.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块)。

+

例子,假设有一个名为 foo.js 的文件:

+
const circle = require('./circle.js');
+console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`);
+

在第一行中,foo.js 加载了同一目录下的 circle.js 模块。

+

circle.js 文件的内容为:

+
const { PI } = Math;
+
+exports.area = (r) => PI * r ** 2;
+
+exports.circumference = (r) => 2 * PI * r;
+

circle.js 模块导出了 area() 和 circumference() 两个函数。 通过在特殊的 exports 对象上指定额外的属性,函数和对象可以被添加到模块的根部。

+

模块内的本地变量是私有的,因为模块被 Node.js 包装在一个函数中(详见模块包装器)。 在这个例子中,变量 PI 是 circle.js 私有的。

+

module.exports属性可以被赋予一个新的值(例如函数或对象)。

+

如下,bar.js 会用到 square 模块,square 导出一个构造函数:

+
const square = require('./square.js');
+const mySquare = square(2);
+console.log(`正方形的面积是 ${mySquare.area()}`);
+square 模块定义在 square.js 中:
+
+// 赋值给 `exports` 不会修改模块,必须使用 `module.exports`
+module.exports = function(width) {
+  return {
+    area: () => width ** 2
+  };
+};
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/overview.html b/app/src/main/assets/docs/overview.html new file mode 100644 index 00000000..5769cb99 --- /dev/null +++ b/app/src/main/assets/docs/overview.html @@ -0,0 +1,79 @@ + + + + + Index | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ +
+

目录

+ +
+ +
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/qa.html b/app/src/main/assets/docs/qa.html new file mode 100644 index 00000000..96139d94 --- /dev/null +++ b/app/src/main/assets/docs/qa.html @@ -0,0 +1,79 @@ + + + + + Index | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ +
+

目录

+ +
+ +
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/shell.html b/app/src/main/assets/docs/shell.html new file mode 100644 index 00000000..2b2269b6 --- /dev/null +++ b/app/src/main/assets/docs/shell.html @@ -0,0 +1,459 @@ + + + + + shell函数 | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

shell即Unix Shell,在类Unix系统提供与操作系统交互的一系列命令。

+

很多程序可以用来执行shell命令,例如终端模拟器。

+

在Auto.js大致等同于用adb执行命令"adb shell"。其实现包括两种方式:

+
    +
  • 通过java.lang.Runtime.exec执行(shell, Tap, Home等函数)
  • +
  • 通过内嵌终端模拟器执行(RootAutomator, Shell等对象)
  • +
+

shell函数#

+
Stability: 2 - Stable

shell(cmd[, root = false])#

+
    +
  • cmd <string> 要执行的命令
  • +
  • root <Boolean> 是否以root权限运行,默认为false。
  • +
+

返回运行一个对象表示命令的执行结果。其属性如下:

+
    +
  • code <number> 返回码。执行成功时为0,失败时为非0的数字。
  • +
  • result <string> 运行结果(stdout输出结果)
  • +
  • error \ 运行的错误信息(stderr输出结果)。例如执行需要root权限的命令但没有授予root权限会返回错误信息"Permission denied"。
  • +
+

示例(强制停止微信) :

+
var result = shell("am force-stop com.tencent.mm", true);
+log(result);
+console.show();
+if(result.code == 0){
+  toast("执行成功");
+}else{
+  toast("执行失败!请到控制台查看错误信息");
+}
+

Shell#

+
Stability: 2 - Stable

shell函数通过用来一次性执行单条命令并获取结果。如果有多条命令需要执行,用Shell对象的效率更高。这是因为,每次运行shell函数都会打开一个单独的shell进程并在运行结束后关闭他,这个过程需要一定的时间;而Shell对象自始至终使用同一个shell进程。

+

Shell(root = false)#

+
    +
  • root <Boolean> 是否以root权限运行一个shell进程。这将会影响其后使用该Shell对象执行的命令的权限
  • +
+

Shell对象的"构造函数"。

+
var sh = new Shell(true);
+sh.exec("am force-stop com.tencent.mm");
+sh.exit();
+

Shell.exec(cmd)#

+
+

执行命令cmd。该函数不会返回任何值。

+

注意,命令执行是"异步"的、非阻塞的。也就是不会等待命令完成后才继续向下执行。

+

尽管这样的设计使用起来有很多不便之处,但受限于终端模拟器,暂时没有解决方式;如果后续能找到解决方案,则将提供Shell.execAndWaitFor函数。

+

Shell.exit()#

+

直接退出shell。这意味着正在执行的命令会被强制退出。

+

Shell.exitAndWaitFor()#

+

执行"exit"命令并等待执行命令执行完成、退出shell。

+

此函数会执行exit命令来正常退出shell。

+

Shell.setCallback(callback)#

+
+

设置该Shell的回调函数,以便监听Shell的输出。可以包括以下属性:

+
    +
  • onOutput <function> 每当shell有新的输出时便会调用该函数。其参数是一个字符串。
  • +
  • onNewLine <function> 每当shell有新的一行输出时便会调用该函数。其参数是一个字符串(不包括最后的换行符)。
  • +
+

例如:

+
var sh = new Shell();
+sh.setCallback({
+    onNewLine: function(line){
+        log(line);
+    }
+})
+while(true){
+    var cmd = dialogs.rawInput("请输入要执行的命令,输入exit退出");
+    if(cmd == "exit"){
+        break;
+    }
+    sh.exec(cmd);
+}
+sh.exit();
+

附录: shell命令简介#

+

以下关于shell命令的资料来自AndroidStudio用户指南:Shell命令

+

am命令#

+

am命令即Activity Manager命令,用于管理应用程序活动、服务等。

+

以下命令均以"am "开头,例如"shell(\"am start -p com.tencent.mm\");"(启动微信)

+

start [options] intent#

+

启动 intent 指定的 Activity(应用程序活动)。
请参阅 intent 参数的规范

+

选项包括:

+
    +
  • -D:启用调试。
  • +
  • -W:等待启动完成。
  • +
  • --start-profiler file:启动分析器并将结果发送到 file。
  • +
  • -P file:类似于 --start-profiler,但当应用进入空闲状态时分析停止。
  • +
  • -R count:重复 Activity 启动 count 次数。在每次重复前,将完成顶部 Activity。
  • +
  • -S:启动 Activity 前强行停止目标应用。
  • +
  • --opengl-trace:启用 OpenGL 函数的跟踪。
  • +
  • --user user_id | current:指定要作为哪个用户运行;如果未指定,则作为当前用户运行。
  • +
+

startservice [options] intent#

+

启动 intent 指定的 Service(服务)。
请参阅 intent 参数的规范
选项包括:

+
    +
  • --user user_id | current:指定要作为哪个用户运行;如果未指定,则作为当前用户运行。
  • +
+

force-stop package#

+

强行停止与 package(应用包名)关联的所有应用。

+

kill [options] package#

+

终止与 package(应用包名)关联的所有进程。此命令仅终止可安全终止且不会影响用户体验的进程。
选项包括:

+
    +
  • --user user_id | all | current:指定将终止其进程的用户;如果未指定,则终止所有用户的进程。
  • +
+

kill-all#

+

终止所有后台进程。

+

broadcast [options] intent#

+

发出广播 intent。 +请参阅 intent 参数的规范

+

选项包括:

+
    +
  • [--user user_id | all | current]:指定要发送到的用户;如果未指定,则发送到所有用户。
  • +
+

instrument [options] component#

+

使用 Instrumentation 实例启动监控。通常,目标 component 是表单 test_package/runner_class。
选项包括:

+
    +
  • -r:输出原始结果(否则对 report_key_streamresult 进行解码)。与 [-e perf true] 结合使用以生成性能测量的原始输出。
  • +
  • -e name value:将参数 name 设为 value。对于测试运行器,通用表单为 -e testrunner_flag value[,value...]。
  • +
  • -p file:将分析数据写入 file。
  • +
  • -w:先等待仪器完成,然后再返回。测试运行器需要使用此选项。
  • +
  • --no-window-animation:运行时关闭窗口动画。
  • +
  • --user user_id | current:指定仪器在哪个用户中运行;如果未指定,则在当前用户中运行。
  • +
  • profile start process file 启动 process 的分析器,将结果写入 file。
  • +
  • profile stop process 停止 process 的分析器。
  • +
+

dumpheap [options] process file#

+

转储 process 的堆,写入 file。

+

选项包括:

+
    +
  • --user [user_id|current]:提供进程名称时,指定要转储的进程用户;如果未指定,则使用当前用户。
  • +
  • -n:转储原生堆,而非托管堆。
  • +
  • set-debug-app [options] package 将应用 package 设为调试。
  • +
+

选项包括:

+
    +
  • -w:应用启动时等待调试程序。
  • +
  • --persistent:保留此值。
  • +
  • clear-debug-app 使用 set-debug-app 清除以前针对调试用途设置的软件包。
  • +
+

monitor [options] 启动对崩溃或 ANR 的监控。#

+

选项包括:

+
    +
  • --gdb:在崩溃/ANR 时在给定端口上启动 gdbserv。

    screen-compat <on> | <off> package#

    +控制 package 的屏幕兼容性模式。
  • +
+

display-size [reset|widthxheight]#

+

替换模拟器/设备显示尺寸。此命令对于在不同尺寸的屏幕上测试您的应用非常有用,它支持使用大屏设备模仿小屏幕分辨率(反之亦然)。
示例:

+
shell("am display-size 1280x800", true);
+

display-density dpi#

+

替换模拟器/设备显示密度。此命令对于在不同密度的屏幕上测试您的应用非常有用,它支持使用低密度屏幕在高密度环境环境上进行测试(反之亦然)。
示例:

+
shell("am display-density 480", true);
+

to-uri intent#

+

将给定的 intent 规范以 URI 的形式输出。 +请参阅 intent 参数的规范

+

to-intent-uri intent#

+

将给定的 intent 规范以 intent:URI 的形式输出。 +请参阅 intent 参数的规范。

+

intent参数的规范#

+

对于采用 intent 参数的 am 命令,您可以使用以下选项指定 intent:

+
    +
  • -a action
    指定 intent 操作,如“android.intent.action.VIEW”。此指定只能声明一次。
  • +
  • -d data_uri
    指定 intent 数据 URI,如“content://contacts/people/1”。此指定只能声明一次。
  • +
  • -t mime_type
    指定 intent MIME 类型,如“image/png”。此指定只能声明一次。
  • +
  • -c category
    指定 intent 类别,如“android.intent.category.APP_CONTACTS”。
  • +
  • -n component
    指定带有软件包名称前缀的组件名称以创建显式 intent,如“com.example.app/.ExampleActivity”。
  • +
  • -f flags
    将标志添加到 setFlags() 支持的 intent。
  • +
  • --esn extra_key
    添加一个 null extra。URI intent 不支持此选项。
  • +
  • -e|--es extra_key extra_string_value
    添加字符串数据作为键值对。
  • +
  • --ez extra_key extra_boolean_value
    添加布尔型数据作为键值对。
  • +
  • --ei extra_key extra_int_value
    添加整数型数据作为键值对。
  • +
  • --el extra_key extra_long_value
    添加长整型数据作为键值对。
  • +
  • --ef extra_key extra_float_value
    添加浮点型数据作为键值对。
  • +
  • --eu extra_key extra_uri_value
    添加 URI 数据作为键值对。
  • +
  • --ecn extra_key extra_component_name_value
    添加组件名称,将其作为 ComponentName 对象进行转换和传递。
  • +
  • --eia extra_key extra_int_value[,extra_int_value...]
    添加整数数组。
  • +
  • --ela extra_key extra_long_value[,extra_long_value...]
    添加长整型数组。
  • +
  • --efa extra_key extra_float_value[,extra_float_value...]
    添加浮点型数组。
  • +
  • --grant-read-uri-permission
    包含标志 FLAG_GRANT_READ_URI_PERMISSION。
  • +
  • --grant-write-uri-permission
    包含标志 FLAG_GRANT_WRITE_URI_PERMISSION。
  • +
  • --debug-log-resolution
    包含标志 FLAG_DEBUG_LOG_RESOLUTION。
  • +
  • --exclude-stopped-packages
    包含标志 FLAG_EXCLUDE_STOPPED_PACKAGES。
  • +
  • --include-stopped-packages
    包含标志 FLAG_INCLUDE_STOPPED_PACKAGES。
  • +
  • --activity-brought-to-front
    包含标志 FLAG_ACTIVITY_BROUGHT_TO_FRONT。
  • +
  • --activity-clear-top
    包含标志 FLAG_ACTIVITY_CLEAR_TOP。
  • +
  • --activity-clear-when-task-reset
    包含标志 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET。
  • +
  • --activity-exclude-from-recents
    包含标志 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS。
  • +
  • --activity-launched-from-history
    包含标志 FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY。
  • +
  • --activity-multiple-task
    包含标志 FLAG_ACTIVITY_MULTIPLE_TASK。
  • +
  • --activity-no-animation
    包含标志 FLAG_ACTIVITY_NO_ANIMATION。
  • +
  • --activity-no-history
    包含标志 FLAG_ACTIVITY_NO_HISTORY。
  • +
  • --activity-no-user-action
    包含标志 FLAG_ACTIVITY_NO_USER_ACTION。
  • +
  • --activity-previous-is-top
    包含标志 FLAG_ACTIVITY_PREVIOUS_IS_TOP。
  • +
  • --activity-reorder-to-front
    包含标志 FLAG_ACTIVITY_REORDER_TO_FRONT。
  • +
  • --activity-reset-task-if-needed
    包含标志 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED。
  • +
  • --activity-single-top
    包含标志 FLAG_ACTIVITY_SINGLE_TOP。
  • +
  • --activity-clear-task
    包含标志 FLAG_ACTIVITY_CLEAR_TASK。
  • +
  • --activity-task-on-home
    包含标志 FLAG_ACTIVITY_TASK_ON_HOME。
  • +
  • --receiver-registered-only
    包含标志 FLAG_RECEIVER_REGISTERED_ONLY。
  • +
  • --receiver-replace-pending
    包含标志 FLAG_RECEIVER_REPLACE_PENDING。
  • +
  • --selector
    需要使用 -d 和 -t 选项以设置 intent 数据和类型。

    URI component package#

    +如果不受上述某一选项的限制,您可以直接指定 URI、软件包名称和组件名称。当参数不受限制时,如果参数包含一个“:”(冒号),则此工具假定参数是一个 URI;如果参数包含一个“/”(正斜杠),则此工具假定参数是一个组件名称;否则,此工具假定参数是一个软件包名称。
  • +
+

应用包名#

+

所谓应用包名,是唯一确定应用的标识。例如微信的包名是"com.tencent.mm", QQ的包名是"com.tencent.mobileqq"。
要获取一个应用的包名,可以通过函数getPackageName(appName)获取。参见帮助->其他一般函数。

+

pm命令#

+

pm命令用于管理应用程序,例如卸载应用、冻结应用等。
以下命令均以"pm "开头,例如"shell(\"pm disable com.tencent.mm\");"(冻结微信)

+

list packages [options] filter#

+

输出所有软件包,或者,仅输出包名称包含 filter 中的文本的软件包。
选项:

+
    +
  • -f:查看它们的关联文件。
  • +
  • -d:进行过滤以仅显示已停用的软件包。
  • +
  • -e:进行过滤以仅显示已启用的软件包。
  • +
  • -s:进行过滤以仅显示系统软件包。
  • +
  • -3:进行过滤以仅显示第三方软件包。
  • +
  • -i:查看软件包的安装程序。
  • +
  • -u:也包括卸载的软件包。
  • +
  • --user user_id:要查询的用户空间。
  • +
+

list permission-groups#

+

输出所有已知的权限组。

+

list permissions [options] group#

+

输出所有已知权限,或者,仅输出 group 中的权限。
选项:

+
    +
  • -g:按组加以组织。
  • +
  • -f:输出所有信息。
  • +
  • -s:简短摘要。
  • +
  • -d:仅列出危险权限。
  • +
  • -u:仅列出用户将看到的权限。
  • +
+

list instrumentation [options]#

+

列出所有测试软件包。
选项:

+
    +
  • -f:列出用于测试软件包的 APK 文件。
  • +
  • target_package:列出仅用于此应用的测试软件包。
  • +
+

list features#

+

输出系统的所有功能。

+

list libraries#

+

输出当前设备支持的所有库。

+

list users#

+

输出系统上的所有用户。

+

path package#

+

输出给定 package 的 APK 的路径。

+

install [options] path#

+

将软件包(通过 path 指定)安装到系统。
选项:

+
    +
  • -l:安装具有转发锁定功能的软件包。
  • +
  • -r:重新安装现有应用,保留其数据。
  • +
  • -t:允许安装测试 APK。
  • +
  • -i installer_package_name:指定安装程序软件包名称。
  • +
  • -s:在共享的大容量存储(如 sdcard)上安装软件包。
  • +
  • -f:在内部系统内存上安装软件包。
  • +
  • -d:允许版本代码降级。
  • +
  • -g:授予应用清单文件中列出的所有权限。
  • +
+

uninstall [options] package#

+

从系统中卸载软件包。
选项:

+
    +
  • -k:移除软件包后保留数据和缓存目录。

    clear package#

    +删除与软件包关联的所有数据。
  • +
+

enable package_or_component#

+

启用给定软件包或组件(作为“package/class”写入)。

+

disable package_or_component#

+

停用给定软件包或组件(作为“package/class”写入)。

+

disable-user [options] package_or_component#

+

选项:

+
    +
  • --user user_id:要停用的用户。

    grant package_name permission#

    +向应用授予权限。在运行 Android 6.0(API 级别 23)及更高版本的设备上,可以是应用清单中声明的任何权限。在运行 Android 5.1(API 级别 22)和更低版本的设备上,必须是应用定义的可选权限。
  • +
+

revoke package_name permission#

+

从应用中撤销权限。在运行 Android 6.0(API 级别 23)及更高版本的设备上,可以是应用清单中声明的任何权限。在运行 Android 5.1(API 级别 22)和更低版本的设备上,必须是应用定义的可选权限。

+

set-install-location location#

+

更改默认安装位置。位置值:

+
    +
  • 0:自动—让系统决定最佳位置。
  • +
  • 1:内部—安装在内部设备存储上。
  • +
  • 2:外部—安装在外部介质上。
  • +
+
+

注:此命令仅用于调试目的;使用此命令会导致应用中断和其他意外行为。

+
+

get-install-location#

+

返回当前安装位置。返回值:

+
    +
  • 0 [auto]:让系统决定最佳位置。
  • +
  • 1 [internal]:安装在内部设备存储上
  • +
  • 2 [external]:安装在外部介质上
  • +
+

set-permission-enforced permission [true|false]#

+

指定是否应强制执行给定的权限。

+

trim-caches desired_free_space#

+

减少缓存文件以达到给定的可用空间。

+

create-user user_name#

+

使用给定的 user_name 创建新用户,输出新用户的标识符。

+

remove-user user_id#

+

移除具有给定的 user_id 的用户,删除与该用户关联的所有数据。

+

get-max-users#

+

输出设备支持的最大用户数。

+

其他命令#

+

进行屏幕截图#

+

screencap 命令是一个用于对设备显示屏进行屏幕截图的 shell 实用程序。在 shell 中,此语法为:

+
screencap filename
+

例如:

+
$ shell("screencap /sdcard/screen.png");
+

列表文件#

+
ls filepath
+

例如:

+
log(shell("ls /system/bin").result);
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/timers.html b/app/src/main/assets/docs/timers.html new file mode 100644 index 00000000..a55d17f3 --- /dev/null +++ b/app/src/main/assets/docs/timers.html @@ -0,0 +1,133 @@ + + + + + Timers | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

Timers#

+
Stability: 2 - Stable

timers 模块暴露了一个全局的 API,用于在某个未来时间段调用调度函数。 因为定时器函数是全局的,所以使用该 API 无需调用 timers.*

+

Auto.js 中的计时器函数实现了与 Web 浏览器提供的定时器类似的 API,除了它使用了一个不同的内部实现,它是基于 Android Looper-Handler消息循环机制构建的。其实现机制与Node.js比较相似。

+

setImmediate(callback[, ...args])#

+
    +
  • callback <Function> 在Looper循环的当前回合结束时要调用的函数。
  • +
  • ...args <any> 当调用 callback 时要传入的可选参数。
  • +
+

预定立即执行的 callback,它是在 I/O 事件的回调之后被触发。 返回一个用于 clearImmediate() 的 id。

+

当多次调用 setImmediate() 时,callback 函数会按照它们被创建的顺序依次执行。 每次事件循环迭代都会处理整个回调队列。 如果一个立即定时器是被一个正在执行的回调排入队列的,则该定时器直到下一次事件循环迭代才会被触发。

+

setInterval(callback, delay[, ...args])#

+
    +
  • callback <Function> 当定时器到点时要调用的函数。
  • +
  • delay <number> 调用 callback 之前要等待的毫秒数。
  • +
  • ...args <any> 当调用 callback 时要传入的可选参数。
  • +
+

预定每隔 delay 毫秒重复执行的 callback。 返回一个用于 clearInterval() 的 id。

+

当 delay 小于 0 时,delay 会被设为 0。

+

setTimeout(callback, delay[, ...args])#

+
    +
  • callback <Function> 当定时器到点时要调用的函数。
  • +
  • delay <number> 调用 callback 之前要等待的毫秒数。
  • +
  • ...args <any> 当调用 callback 时要传入的可选参数。
  • +
+

预定在 delay 毫秒之后执行的单次 callback。 返回一个用于 clearTimeout() 的 id。

+

callback 可能不会精确地在 delay 毫秒被调用。 Auto.js 不能保证回调被触发的确切时间,也不能保证它们的顺序。 回调会在尽可能接近所指定的时间上调用。

+

当 delay 小于 0 时,delay 会被设为 0。

+

setImmediate()、setInterval() 和 setTimeout() 方法每次都会返回表示预定的计时器的id。 它们可用于取消定时器并防止触发。

+

clearImmediate(id)#

+
    +
  • id <number> 一个 setImmediate() 返回的 id。
  • +
+

取消一个由 setImmediate() 创建的 Immediate 对象。

+

clearInterval(id)#

+
    +
  • id <number> 一个 setInterval() 返回的 id。
  • +
+

取消一个由 setInterval() 创建的 Timeout 对象。

+

clearTimeout(id)#

+
    +
  • id <number> 一个 setTimeout() 返回的 id。
  • +
+

取消一个由 setTimeout() 创建的 Timeout 对象。

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/ui.html b/app/src/main/assets/docs/ui.html new file mode 100644 index 00000000..d7f61fd2 --- /dev/null +++ b/app/src/main/assets/docs/ui.html @@ -0,0 +1,79 @@ + + + + + Index | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ +
+

目录

+ +
+ +
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/util.html b/app/src/main/assets/docs/util.html new file mode 100644 index 00000000..7860ca6b --- /dev/null +++ b/app/src/main/assets/docs/util.html @@ -0,0 +1,1212 @@ + + + + + Util | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ + + +
+

Util#

+
Stability: 2 - Stable

The util module is primarily designed to support the needs of Node.js' own +internal APIs. However, many of the utilities are useful for application and +module developers as well. It can be accessed using:

+
const util = require('util');
+
+

util.callbackify(original)#

+ +

Takes an async function (or a function that returns a Promise) and returns a +function following the Node.js error first callback style. In the callback, the +first argument will be the rejection reason (or null if the Promise resolved), +and the second argument will be the resolved value.

+

For example:

+
const util = require('util');
+
+async function fn() {
+  return await Promise.resolve('hello world');
+}
+const callbackFunction = util.callbackify(fn);
+
+callbackFunction((err, ret) => {
+  if (err) throw err;
+  console.log(ret);
+});
+
+

Will print:

+
hello world
+
+

Note:

+
    +
  • The callback is executed asynchronously, and will have a limited stack trace. +If the callback throws, the process will emit an 'uncaughtException' +event, and if not handled will exit.

    +
  • +
  • Since null has a special meaning as the first argument to a callback, if a +wrapped function rejects a Promise with a falsy value as a reason, the value +is wrapped in an Error with the original value stored in a field named +reason.

    +
    function fn() {
    +  return Promise.reject(null);
    +}
    +const callbackFunction = util.callbackify(fn);
    +
    +callbackFunction((err, ret) => {
    +  // When the Promise was rejected with `null` it is wrapped with an Error and
    +  // the original value is stored in `reason`.
    +  err && err.hasOwnProperty('reason') && err.reason === null;  // true
    +});
    +
    +
  • +
+

util.debuglog(section)#

+
    +
  • section <string> A string identifying the portion of the application for +which the debuglog function is being created.
  • +
  • Returns: <Function> The logging function
  • +
+

The util.debuglog() method is used to create a function that conditionally +writes debug messages to stderr based on the existence of the NODE_DEBUG +environment variable. If the section name appears within the value of that +environment variable, then the returned function operates similar to +console.error(). If not, then the returned function is a no-op.

+

For example:

+
const util = require('util');
+const debuglog = util.debuglog('foo');
+
+debuglog('hello from foo [%d]', 123);
+
+

If this program is run with NODE_DEBUG=foo in the environment, then +it will output something like:

+
FOO 3245: hello from foo [123]
+
+

where 3245 is the process id. If it is not run with that +environment variable set, then it will not print anything.

+

Multiple comma-separated section names may be specified in the NODE_DEBUG +environment variable. For example: NODE_DEBUG=fs,net,tls.

+

util.deprecate(function, string)#

+

The util.deprecate() method wraps the given function or class in such a way that +it is marked as deprecated.

+ +
const util = require('util');
+
+exports.puts = util.deprecate(function() {
+  for (let i = 0, len = arguments.length; i < len; ++i) {
+    process.stdout.write(arguments[i] + '\n');
+  }
+}, 'util.puts: Use console.log instead');
+
+

When called, util.deprecate() will return a function that will emit a +DeprecationWarning using the process.on('warning') event. By default, +this warning will be emitted and printed to stderr exactly once, the first +time it is called. After the warning is emitted, the wrapped function +is called.

+

If either the --no-deprecation or --no-warnings command line flags are +used, or if the process.noDeprecation property is set to true prior to +the first deprecation warning, the util.deprecate() method does nothing.

+

If the --trace-deprecation or --trace-warnings command line flags are set, +or the process.traceDeprecation property is set to true, a warning and a +stack trace are printed to stderr the first time the deprecated function is +called.

+

If the --throw-deprecation command line flag is set, or the +process.throwDeprecation property is set to true, then an exception will be +thrown when the deprecated function is called.

+

The --throw-deprecation command line flag and process.throwDeprecation +property take precedence over --trace-deprecation and +process.traceDeprecation.

+

util.format(format[, ...args])#

+
    +
  • format <string> A printf-like format string.
  • +
+

The util.format() method returns a formatted string using the first argument +as a printf-like format.

+

The first argument is a string containing zero or more placeholder tokens. +Each placeholder token is replaced with the converted value from the +corresponding argument. Supported placeholders are:

+
    +
  • %s - String.
  • +
  • %d - Number (integer or floating point value).
  • +
  • %i - Integer.
  • +
  • %f - Floating point value.
  • +
  • %j - JSON. Replaced with the string '[Circular]' if the argument +contains circular references.
  • +
  • %o - Object. A string representation of an object +with generic JavaScript object formatting. +Similar to util.inspect() with options { showHidden: true, depth: 4, showProxy: true }. +This will show the full object including non-enumerable symbols and properties.
  • +
  • %O - Object. A string representation of an object +with generic JavaScript object formatting. +Similar to util.inspect() without options. +This will show the full object not including non-enumerable symbols and properties.
  • +
  • %% - single percent sign ('%'). This does not consume an argument.
  • +
+

If the placeholder does not have a corresponding argument, the placeholder is +not replaced.

+
util.format('%s:%s', 'foo');
+// Returns: 'foo:%s'
+
+

If there are more arguments passed to the util.format() method than the number +of placeholders, the extra arguments are coerced into strings then concatenated +to the returned string, each delimited by a space. Excessive arguments whose +typeof is 'object' or 'symbol' (except null) will be transformed by +util.inspect().

+
util.format('%s:%s', 'foo', 'bar', 'baz'); // 'foo:bar baz'
+
+

If the first argument is not a string then util.format() returns +a string that is the concatenation of all arguments separated by spaces. +Each argument is converted to a string using util.inspect().

+
util.format(1, 2, 3); // '1 2 3'
+
+

If only one argument is passed to util.format(), it is returned as it is +without any formatting.

+
util.format('%% %s'); // '%% %s'
+
+

util.inherits(constructor, superConstructor)#

+

Note: Usage of util.inherits() is discouraged. Please use the ES6 class +and extends keywords to get language level inheritance support. Also note +that the two styles are semantically incompatible.

+ +

Inherit the prototype methods from one constructor into another. The +prototype of constructor will be set to a new object created from +superConstructor.

+

As an additional convenience, superConstructor will be accessible +through the constructor.super_ property.

+
const util = require('util');
+const EventEmitter = require('events');
+
+function MyStream() {
+  EventEmitter.call(this);
+}
+
+util.inherits(MyStream, EventEmitter);
+
+MyStream.prototype.write = function(data) {
+  this.emit('data', data);
+};
+
+const stream = new MyStream();
+
+console.log(stream instanceof EventEmitter); // true
+console.log(MyStream.super_ === EventEmitter); // true
+
+stream.on('data', (data) => {
+  console.log(`Received data: "${data}"`);
+});
+stream.write('It works!'); // Received data: "It works!"
+
+

ES6 example using class and extends

+
const EventEmitter = require('events');
+
+class MyStream extends EventEmitter {
+  write(data) {
+    this.emit('data', data);
+  }
+}
+
+const stream = new MyStream();
+
+stream.on('data', (data) => {
+  console.log(`Received data: "${data}"`);
+});
+stream.write('With ES6');
+
+

util.inspect(object[, options])#

+
    +
  • object <any> Any JavaScript primitive or Object.
  • +
  • options <Object>
      +
    • showHidden <boolean> If true, the object's non-enumerable symbols and +properties will be included in the formatted result. Defaults to false.
    • +
    • depth <number> Specifies the number of times to recurse while formatting +the object. This is useful for inspecting large complicated objects. +Defaults to 2. To make it recurse indefinitely pass null.
    • +
    • colors <boolean> If true, the output will be styled with ANSI color +codes. Defaults to false. Colors are customizable, see +Customizing util.inspect colors.
    • +
    • customInspect <boolean> If false, then custom inspect(depth, opts) +functions exported on the object being inspected will not be called. +Defaults to true.
    • +
    • showProxy <boolean> If true, then objects and functions that are +Proxy objects will be introspected to show their target and handler +objects. Defaults to false.
    • +
    • maxArrayLength <number> Specifies the maximum number of array and +TypedArray elements to include when formatting. Defaults to 100. Set to +null to show all array elements. Set to 0 or negative to show no array +elements.
    • +
    • breakLength <number> The length at which an object's keys are split +across multiple lines. Set to Infinity to format an object as a single +line. Defaults to 60 for legacy compatibility.
    • +
    +
  • +
+

The util.inspect() method returns a string representation of object that is +primarily useful for debugging. Additional options may be passed that alter +certain aspects of the formatted string.

+

The following example inspects all properties of the util object:

+
const util = require('util');
+
+console.log(util.inspect(util, { showHidden: true, depth: null }));
+
+

Values may supply their own custom inspect(depth, opts) functions, when +called these receive the current depth in the recursive inspection, as well as +the options object passed to util.inspect().

+

Customizing util.inspect colors#

+ +

Color output (if enabled) of util.inspect is customizable globally +via the util.inspect.styles and util.inspect.colors properties.

+

util.inspect.styles is a map associating a style name to a color from +util.inspect.colors.

+

The default styles and associated colors are:

+
    +
  • number - yellow
  • +
  • boolean - yellow
  • +
  • string - green
  • +
  • date - magenta
  • +
  • regexp - red
  • +
  • null - bold
  • +
  • undefined - grey
  • +
  • special - cyan (only applied to functions at this time)
  • +
  • name - (no styling)
  • +
+

The predefined color codes are: white, grey, black, blue, cyan, +green, magenta, red and yellow. There are also bold, italic, +underline and inverse codes.

+

Color styling uses ANSI control codes that may not be supported on all +terminals.

+

Custom inspection functions on Objects#

+ +

Objects may also define their own [util.inspect.custom](depth, opts) +(or, equivalently inspect(depth, opts)) function that util.inspect() will +invoke and use the result of when inspecting the object:

+
const util = require('util');
+
+class Box {
+  constructor(value) {
+    this.value = value;
+  }
+
+  inspect(depth, options) {
+    if (depth < 0) {
+      return options.stylize('[Box]', 'special');
+    }
+
+    const newOptions = Object.assign({}, options, {
+      depth: options.depth === null ? null : options.depth - 1
+    });
+
+    // Five space padding because that's the size of "Box< ".
+    const padding = ' '.repeat(5);
+    const inner = util.inspect(this.value, newOptions)
+                      .replace(/\n/g, `\n${padding}`);
+    return `${options.stylize('Box', 'special')}< ${inner} >`;
+  }
+}
+
+const box = new Box(true);
+
+util.inspect(box);
+// Returns: "Box< true >"
+
+

Custom [util.inspect.custom](depth, opts) functions typically return a string +but may return a value of any type that will be formatted accordingly by +util.inspect().

+
const util = require('util');
+
+const obj = { foo: 'this will not show up in the inspect() output' };
+obj[util.inspect.custom] = function(depth) {
+  return { bar: 'baz' };
+};
+
+util.inspect(obj);
+// Returns: "{ bar: 'baz' }"
+
+

A custom inspection method can alternatively be provided by exposing +an inspect(depth, opts) method on the object:

+
const util = require('util');
+
+const obj = { foo: 'this will not show up in the inspect() output' };
+obj.inspect = function(depth) {
+  return { bar: 'baz' };
+};
+
+util.inspect(obj);
+// Returns: "{ bar: 'baz' }"
+
+

util.inspect.custom#

+

A Symbol that can be used to declare custom inspect functions, see +Custom inspection functions on Objects.

+

util.inspect.defaultOptions#

+

The defaultOptions value allows customization of the default options used by +util.inspect. This is useful for functions like console.log or +util.format which implicitly call into util.inspect. It shall be set to an +object containing one or more valid util.inspect() options. Setting +option properties directly is also supported.

+
const util = require('util');
+const arr = Array(101).fill(0);
+
+console.log(arr); // logs the truncated array
+util.inspect.defaultOptions.maxArrayLength = null;
+console.log(arr); // logs the full array
+
+

util.promisify(original)#

+ +

Takes a function following the common Node.js callback style, i.e. taking a +(err, value) => ... callback as the last argument, and returns a version +that returns promises.

+

For example:

+
const util = require('util');
+const fs = require('fs');
+
+const stat = util.promisify(fs.stat);
+stat('.').then((stats) => {
+  // Do something with `stats`
+}).catch((error) => {
+  // Handle the error.
+});
+
+

Or, equivalently using async functions:

+
const util = require('util');
+const fs = require('fs');
+
+const stat = util.promisify(fs.stat);
+
+async function callStat() {
+  const stats = await stat('.');
+  console.log(`This directory is owned by ${stats.uid}`);
+}
+
+

If there is an original[util.promisify.custom] property present, promisify +will return its value, see Custom promisified functions.

+

promisify() assumes that original is a function taking a callback as its +final argument in all cases, and the returned function will result in undefined +behavior if it does not.

+

Custom promisified functions#

+

Using the util.promisify.custom symbol one can override the return value of +util.promisify():

+
const util = require('util');
+
+function doSomething(foo, callback) {
+  // ...
+}
+
+doSomething[util.promisify.custom] = function(foo) {
+  return getPromiseSomehow();
+};
+
+const promisified = util.promisify(doSomething);
+console.log(promisified === doSomething[util.promisify.custom]);
+// prints 'true'
+
+

This can be useful for cases where the original function does not follow the +standard format of taking an error-first callback as the last argument.

+

util.promisify.custom#

+ +

A Symbol that can be used to declare custom promisified variants of functions, +see Custom promisified functions.

+

Class: util.TextDecoder#

+
Stability: 1 - Experimental

An implementation of the WHATWG Encoding Standard TextDecoder API.

+
const decoder = new TextDecoder('shift_jis');
+let string = '';
+let buffer;
+while (buffer = getNextChunkSomehow()) {
+  string += decoder.decode(buffer, { stream: true });
+}
+string += decoder.decode(); // end-of-stream
+
+

WHATWG Supported Encodings#

+

Per the WHATWG Encoding Standard, the encodings supported by the +TextDecoder API are outlined in the tables below. For each encoding, +one or more aliases may be used.

+

Different Node.js build configurations support different sets of encodings. +While a very basic set of encodings is supported even on Node.js builds without +ICU enabled, support for some encodings is provided only when Node.js is built +with ICU and using the full ICU data (see Internationalization).

+

Encodings Supported Without ICU#

+ + + + + + + + + + + + + + + + + +
EncodingAliases
'utf-8''unicode-1-1-utf-8', 'utf8'
'utf-16le''utf-16'
+

Encodings Supported by Default (With ICU)#

+ + + + + + + + + + + + + + + + + + + + +
EncodingAliases
'utf-8''unicode-1-1-utf-8', 'utf8'
'utf-16le''utf-16'
'utf-16be'
+

Encodings Requiring Full ICU Data#

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingAliases
'ibm866''866', 'cp866', 'csibm866'
'iso-8859-2''csisolatin2', 'iso-ir-101', 'iso8859-2', 'iso88592', 'iso_8859-2', 'iso_8859-2:1987', 'l2', 'latin2'
'iso-8859-3''csisolatin3', 'iso-ir-109', 'iso8859-3', 'iso88593', 'iso_8859-3', 'iso_8859-3:1988', 'l3', 'latin3'
'iso-8859-4''csisolatin4', 'iso-ir-110', 'iso8859-4', 'iso88594', 'iso_8859-4', 'iso_8859-4:1988', 'l4', 'latin4'
'iso-8859-5''csisolatincyrillic', 'cyrillic', 'iso-ir-144', 'iso8859-5', 'iso88595', 'iso_8859-5', 'iso_8859-5:1988'
'iso-8859-6''arabic', 'asmo-708', 'csiso88596e', 'csiso88596i', 'csisolatinarabic', 'ecma-114', 'iso-8859-6-e', 'iso-8859-6-i', 'iso-ir-127', 'iso8859-6', 'iso88596', 'iso_8859-6', 'iso_8859-6:1987'
'iso-8859-7''csisolatingreek', 'ecma-118', 'elot_928', 'greek', 'greek8', 'iso-ir-126', 'iso8859-7', 'iso88597', 'iso_8859-7', 'iso_8859-7:1987', 'sun_eu_greek'
'iso-8859-8''csiso88598e', 'csisolatinhebrew', 'hebrew', 'iso-8859-8-e', 'iso-ir-138', 'iso8859-8', 'iso88598', 'iso_8859-8', 'iso_8859-8:1988', 'visual'
'iso-8859-8-i''csiso88598i', 'logical'
'iso-8859-10''csisolatin6', 'iso-ir-157', 'iso8859-10', 'iso885910', 'l6', 'latin6'
'iso-8859-13''iso8859-13', 'iso885913'
'iso-8859-14''iso8859-14', 'iso885914'
'iso-8859-15''csisolatin9', 'iso8859-15', 'iso885915', 'iso_8859-15', 'l9'
'koi8-r''cskoi8r', 'koi', 'koi8', 'koi8_r'
'koi8-u''koi8-ru'
'macintosh''csmacintosh', 'mac', 'x-mac-roman'
'windows-874''dos-874', 'iso-8859-11', 'iso8859-11', 'iso885911', 'tis-620'
'windows-1250''cp1250', 'x-cp1250'
'windows-1251''cp1251', 'x-cp1251'
'windows-1252''ansi_x3.4-1968', 'ascii', 'cp1252', 'cp819', 'csisolatin1', 'ibm819', 'iso-8859-1', 'iso-ir-100', 'iso8859-1', 'iso88591', 'iso_8859-1', 'iso_8859-1:1987', 'l1', 'latin1', 'us-ascii', 'x-cp1252'
'windows-1253''cp1253', 'x-cp1253'
'windows-1254''cp1254', 'csisolatin5', 'iso-8859-9', 'iso-ir-148', 'iso8859-9', 'iso88599', 'iso_8859-9', 'iso_8859-9:1989', 'l5', 'latin5', 'x-cp1254'
'windows-1255''cp1255', 'x-cp1255'
'windows-1256''cp1256', 'x-cp1256'
'windows-1257''cp1257', 'x-cp1257'
'windows-1258''cp1258', 'x-cp1258'
'x-mac-cyrillic''x-mac-ukrainian'
'gbk''chinese', 'csgb2312', 'csiso58gb231280', 'gb2312', 'gb_2312', 'gb_2312-80', 'iso-ir-58', 'x-gbk'
'gb18030'
'big5''big5-hkscs', 'cn-big5', 'csbig5', 'x-x-big5'
'euc-jp''cseucpkdfmtjapanese', 'x-euc-jp'
'iso-2022-jp''csiso2022jp'
'shift_jis''csshiftjis', 'ms932', 'ms_kanji', 'shift-jis', 'sjis', 'windows-31j', 'x-sjis'
'euc-kr''cseuckr', 'csksc56011987', 'iso-ir-149', 'korean', 'ks_c_5601-1987', 'ks_c_5601-1989', 'ksc5601', 'ksc_5601', 'windows-949'
+

Note: The 'iso-8859-16' encoding listed in the WHATWG Encoding Standard +is not supported.

+

new TextDecoder([encoding[, options]])#

+
    +
  • encoding <string> Identifies the encoding that this TextDecoder instance +supports. Defaults to 'utf-8'.
  • +
  • options <Object>
      +
    • fatal <boolean> true if decoding failures are fatal. Defaults to +false. This option is only supported when ICU is enabled (see +Internationalization).
    • +
    • ignoreBOM <boolean> When true, the TextDecoder will include the byte + order mark in the decoded result. When false, the byte order mark will + be removed from the output. This option is only used when encoding is + 'utf-8', 'utf-16be' or 'utf-16le'. Defaults to false.
    • +
    +
  • +
+

Creates an new TextDecoder instance. The encoding may specify one of the +supported encodings or an alias.

+

textDecoder.decode([input[, options]])#

+
+

Decodes the input and returns a string. If options.stream is true, any +incomplete byte sequences occuring at the end of the input are buffered +internally and emitted after the next call to textDecoder.decode().

+

If textDecoder.fatal is true, decoding errors that occur will result in a +TypeError being thrown.

+

textDecoder.encoding#

+
+

The encoding supported by the TextDecoder instance.

+

textDecoder.fatal#

+
+

The value will be true if decoding errors result in a TypeError being +thrown.

+

textDecoder.ignoreBOM#

+
+

The value will be true if the decoding result will include the byte order +mark.

+

Class: util.TextEncoder#

+
Stability: 1 - Experimental

An implementation of the WHATWG Encoding Standard TextEncoder API. All +instances of TextEncoder only support UTF-8 encoding.

+
const encoder = new TextEncoder();
+const uint8array = encoder.encode('this is some data');
+
+

textEncoder.encode([input])#

+
+

UTF-8 encodes the input string and returns a Uint8Array containing the +encoded bytes.

+

textDecoder.encoding#

+
+

The encoding supported by the TextEncoder instance. Always set to 'utf-8'.

+

Deprecated APIs#

+

The following APIs have been deprecated and should no longer be used. Existing +applications and modules should be updated to find alternative approaches.

+

util._extend(target, source)#

+
Stability: 0 - Deprecated: Use Object.assign() instead.

The util._extend() method was never intended to be used outside of internal +Node.js modules. The community found and used it anyway.

+

It is deprecated and should not be used in new code. JavaScript comes with very +similar built-in functionality through Object.assign().

+

util.debug(string)#

+
Stability: 0 - Deprecated: Use console.error() instead.
    +
  • string <string> The message to print to stderr
  • +
+

Deprecated predecessor of console.error.

+

util.error([...strings])#

+
Stability: 0 - Deprecated: Use console.error() instead.
    +
  • ...strings <string> The message to print to stderr
  • +
+

Deprecated predecessor of console.error.

+

util.isArray(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Internal alias for Array.isArray.

+

Returns true if the given object is an Array. Otherwise, returns false.

+
const util = require('util');
+
+util.isArray([]);
+// Returns: true
+util.isArray(new Array());
+// Returns: true
+util.isArray({});
+// Returns: false
+
+

util.isBoolean(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is a Boolean. Otherwise, returns false.

+
const util = require('util');
+
+util.isBoolean(1);
+// Returns: false
+util.isBoolean(0);
+// Returns: false
+util.isBoolean(false);
+// Returns: true
+
+

util.isBuffer(object)#

+
Stability: 0 - Deprecated: Use Buffer.isBuffer() instead.
    +
  • object <any>
  • +
+

Returns true if the given object is a Buffer. Otherwise, returns false.

+
const util = require('util');
+
+util.isBuffer({ length: 0 });
+// Returns: false
+util.isBuffer([]);
+// Returns: false
+util.isBuffer(Buffer.from('hello world'));
+// Returns: true
+
+

util.isDate(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is a Date. Otherwise, returns false.

+
const util = require('util');
+
+util.isDate(new Date());
+// Returns: true
+util.isDate(Date());
+// false (without 'new' returns a String)
+util.isDate({});
+// Returns: false
+
+

util.isError(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is an Error. Otherwise, returns +false.

+
const util = require('util');
+
+util.isError(new Error());
+// Returns: true
+util.isError(new TypeError());
+// Returns: true
+util.isError({ name: 'Error', message: 'an error occurred' });
+// Returns: false
+
+

Note that this method relies on Object.prototype.toString() behavior. It is +possible to obtain an incorrect result when the object argument manipulates +@@toStringTag.

+
const util = require('util');
+const obj = { name: 'Error', message: 'an error occurred' };
+
+util.isError(obj);
+// Returns: false
+obj[Symbol.toStringTag] = 'Error';
+util.isError(obj);
+// Returns: true
+
+

util.isFunction(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is a Function. Otherwise, returns +false.

+
const util = require('util');
+
+function Foo() {}
+const Bar = () => {};
+
+util.isFunction({});
+// Returns: false
+util.isFunction(Foo);
+// Returns: true
+util.isFunction(Bar);
+// Returns: true
+
+

util.isNull(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is strictly null. Otherwise, returns +false.

+
const util = require('util');
+
+util.isNull(0);
+// Returns: false
+util.isNull(undefined);
+// Returns: false
+util.isNull(null);
+// Returns: true
+
+

util.isNullOrUndefined(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is null or undefined. Otherwise, +returns false.

+
const util = require('util');
+
+util.isNullOrUndefined(0);
+// Returns: false
+util.isNullOrUndefined(undefined);
+// Returns: true
+util.isNullOrUndefined(null);
+// Returns: true
+
+

util.isNumber(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is a Number. Otherwise, returns false.

+
const util = require('util');
+
+util.isNumber(false);
+// Returns: false
+util.isNumber(Infinity);
+// Returns: true
+util.isNumber(0);
+// Returns: true
+util.isNumber(NaN);
+// Returns: true
+
+

util.isObject(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is strictly an Object and not a +Function. Otherwise, returns false.

+
const util = require('util');
+
+util.isObject(5);
+// Returns: false
+util.isObject(null);
+// Returns: false
+util.isObject({});
+// Returns: true
+util.isObject(function() {});
+// Returns: false
+
+

util.isPrimitive(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is a primitive type. Otherwise, returns +false.

+
const util = require('util');
+
+util.isPrimitive(5);
+// Returns: true
+util.isPrimitive('foo');
+// Returns: true
+util.isPrimitive(false);
+// Returns: true
+util.isPrimitive(null);
+// Returns: true
+util.isPrimitive(undefined);
+// Returns: true
+util.isPrimitive({});
+// Returns: false
+util.isPrimitive(function() {});
+// Returns: false
+util.isPrimitive(/^$/);
+// Returns: false
+util.isPrimitive(new Date());
+// Returns: false
+
+

util.isRegExp(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is a RegExp. Otherwise, returns false.

+
const util = require('util');
+
+util.isRegExp(/some regexp/);
+// Returns: true
+util.isRegExp(new RegExp('another regexp'));
+// Returns: true
+util.isRegExp({});
+// Returns: false
+
+

util.isString(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is a string. Otherwise, returns false.

+
const util = require('util');
+
+util.isString('');
+// Returns: true
+util.isString('foo');
+// Returns: true
+util.isString(String('foo'));
+// Returns: true
+util.isString(5);
+// Returns: false
+
+

util.isSymbol(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is a Symbol. Otherwise, returns false.

+
const util = require('util');
+
+util.isSymbol(5);
+// Returns: false
+util.isSymbol('foo');
+// Returns: false
+util.isSymbol(Symbol('foo'));
+// Returns: true
+
+

util.isUndefined(object)#

+
Stability: 0 - Deprecated
    +
  • object <any>
  • +
+

Returns true if the given object is undefined. Otherwise, returns false.

+
const util = require('util');
+
+const foo = undefined;
+util.isUndefined(5);
+// Returns: false
+util.isUndefined(foo);
+// Returns: true
+util.isUndefined(null);
+// Returns: false
+
+

util.log(string)#

+
Stability: 0 - Deprecated: Use a third party module instead.
+

The util.log() method prints the given string to stdout with an included +timestamp.

+
const util = require('util');
+
+util.log('Timestamped message.');
+
+

util.print([...strings])#

+
Stability: 0 - Deprecated: Use console.log() instead.

Deprecated predecessor of console.log.

+

util.puts([...strings])#

+
Stability: 0 - Deprecated: Use console.log() instead.

Deprecated predecessor of console.log.

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/widgets-based-automation.html b/app/src/main/assets/docs/widgets-based-automation.html new file mode 100644 index 00000000..3732d9c9 --- /dev/null +++ b/app/src/main/assets/docs/widgets-based-automation.html @@ -0,0 +1,727 @@ + + + + + SimpleActionAutomator | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ +
+

目录

+ + +
+ +
+

SimpleActionAutomator#

+
Stability: 2 - Stable

SimpleActionAutomator提供了一些模拟简单操作的函数,例如点击文字、模拟按键等。这些函数可以直接作为全局函数使用。

+

click(text[, i])#

+
    +
  • text <string> 要点击的文本
  • +
  • i <number> 如果相同的文本在屏幕中出现多次,则i表示要点击第几个文本, i从0开始计算
  • +
+

返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。

+

该函数可以点击大部分包含文字的按钮。例如微信主界面下方的"微信", "联系人", "发现", "我"的按钮。
通常与while同时使用以便点击按钮直至成功。例如:

+
while(!click("扫一扫"));
+

当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部点击成功。

+

i是从0开始计算的, 也就是, click("啦啦啦", 0)表示点击屏幕上第一个"啦啦啦", click("啦啦啦", 1)表示点击屏幕上第二个"啦啦啦"。

+
+

文本所在区域指的是,从文本处向其父视图寻找,直至发现一个可点击的部件为止。

+
+

click(left, top, bottom, right)#

+
    +
  • left <number> 要点击的长方形区域左边与屏幕左边的像素距离
  • +
  • top <number> 要点击的长方形区域上边与屏幕上边的像素距离
  • +
  • bottom <number> 要点击的长方形区域下边与屏幕下边的像素距离
  • +
  • right <number> 要点击的长方形区域右边与屏幕右边的像素距离
  • +
+

注意,该函数一般只用于录制的脚本中使用,在自己写的代码中使用该函数一般不要使用该函数。

+

点击在指定区域的控件。当屏幕中并未包含与该区域严格匹配的区域,或者该区域不能点击时返回false,否则返回true。

+

有些按钮或者部件是图标而不是文字(例如发送朋友圈的照相机图标以及QQ下方的消息、联系人、动态图标),这时不能通过click(text, i)来点击,可以通过描述图标所在的区域来点击。left, bottom, top, right描述的就是点击的区域。

+

至于要定位点击的区域,可以在悬浮窗使用布局分析工具查看控件的bounds属性。

+

通过无障碍服务录制脚本会生成该语句。

+

longClick(text[, i]))#

+
    +
  • text <string> 要长按的文本
  • +
  • i <number> 如果相同的文本在屏幕中出现多次,则i表示要长按第几个文本, i从0开始计算
  • +
+

返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。

+

当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部长按成功。

+

scrollUp([i])#

+
+

找到第i+1个可滑动控件上滑或左滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。

+

另外不加参数时scrollUp()会寻找面积最大的可滑动的控件上滑或左滑,例如微信消息列表等。

+

参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)为滑动第一个可滑动控件。

+

scrollDown([i])#

+
+

找到第i+1个可滑动控件下滑或右滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。

+

另外不加参数时scrollUp()会寻找面积最大的可滑动的控件下滑或右滑。

+

参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)为滑动第一个可滑动控件。

+

setText([i, ]text)#

+
    +
  • i <number> 表示要输入的为第i + 1个输入框
  • +
  • text <string> 要输入的文本
  • +
+

返回是否输入成功。当找不到对应的文本框时返回false。

+

不加参数i则会把所有输入框的文本都置为text。例如setText("测试")

+

这里的输入文本的意思是,把输入框的文本置为text,而不是在原来的文本上追加。

+

input([i, ]text)#

+
    +
  • i <number> 表示要输入的为第i + 1个输入框
  • +
  • text <string> 要输入的文本
  • +
+

返回是否输入成功。当找不到对应的文本框时返回false。

+

不加参数i则会把所有输入框的文本追加内容text。例如input("测试")

+

UiSelector#

+

选择器(UiSelector)是稍微复杂的自动操作脚本所必须。使用选择器的一般步骤是:

+
    +
  1. 用各种筛选条件找出想要的控件,如某个文本控件、列表控件、图片控件
  2. +
  3. 对找出的控件执行想要的操作,如点击、滑动、设置文字、长按
  4. +
+

问题的关键在于如何找出想要的控件。对于文本控件一般通过他的文字来定位他,图片控件则通过id或者图片描述(desc)。选择器所做的就是提供这些筛选条件并给出筛选结果。

+

选择器提供了更强大的定位界面控件与对其进行操作的功能,可以用他们完成更多的自动操作和提取界面信息。
选择器通过附加筛选条件,筛选出符合条件的控件或控件集合,之后可以对这些控件这些操作。
可供选择的筛选条件包括:

+
    +
  • id
  • +
  • text 文本
  • +
  • desc 描述(Content-Description)
  • +
  • className 类名
  • +
  • packageName 包名
  • +
  • bounds 在屏幕上的范围
  • +
  • drawingOrder 绘制顺序
  • +
  • 各种属性,主要包括:
      +
    • clickable 可点击
    • +
    • longClickable 可长按
    • +
    • checkable 可勾选
    • +
    • checked 被勾选
    • +
    • scrollable 可滑动
    • +
    • selected 被选择
    • +
    • editable 可编辑
    • +
    • visibleToUser 可见
    • +
    • enabled 已启用
    • +
    +
  • +
+

要对选择器所确定的筛选条件,对屏幕上的控件进行筛选,调用方法find(), findOne(), untilFind()。其中find(), untilFind()返回控件的集合,findOne()返回一个控件。untilFind和findOne函数会一直寻找直到屏幕上出现满足条件的控件为止。
一个完整的选择器示例如下:

+
var emoj = id("name").packageName("com.tencent.mobileqq").clickable()
+        .className("ImageView").drawingOrder(5).findOne();
+emoj.click();
+

上述代码是找到QQ聊天界面下面的表情按钮(第5个按钮)并点击。也可以简化为:

+
id("name").packageName("com.tencent.mobileqq").clickable()
+       .className("ImageView").click();
+

这段代码意思是,找出id为"name", 包名为"com.tentcent.mobileqq",类名为ImageView的所有可点击控件,对他们执行点击动作。

+

最后的click()函数相当于untilFind().click()。也就是如果只需要在找到控件以后立即进行操作,只需要调用相应的操作函数,而不需要先调用find等函数等到控件再操作。
要获取屏幕上的控件的信息(例如id, text, desc, bounds等),可以开启悬浮窗,使用界面层次查看和界面范围查看。

+

选择器部分内容如果有安卓开发经验会更容易掌握。

+

id(resId)#

+
    +
  • resId <string> 控件的id,以"包名:id/"开头,例如"com.tencent.mm:id/send_btn"。也可以不指定包名,这时会以当前正在运行的应用的包名来补全id。例如id("send_btn"),在QQ界面想当于id("com.tencent.mobileqq:id/send_btn")。
  • +
+

附加id严格匹配筛选条件。

+

控件的id属性通常是可以用来确定控件的唯一标识,如果一个控件有id,那么使用id来找到他是最好的方法。要查看屏幕上的控件的id,可以开启悬浮窗并使用界面工具,点击相应控件即可查看。若查看到的控件id为null, 表示该控件没有id。另外,在列表中会出现多个控件的id相同的情况。例如微信的联系人列表,每个头像的id都是一样的。此时不能用id来唯一确定控件。

+

在QQ界面经常会出现多个id为"name"的控件,在微信上则每个版本的id都会变化。对于这些软件而言比较难用id定位控件。

+

idContains(str)#

+
    +
  • str <string> id要包含的字符串
  • +
+

附加控件id包含字符串str的筛选条件。

+

idStartsWith(prefix)#

+
+

附加id需要以prefix开头的筛选条件。

+

idEndsWith(suffix)#

+
+

附加id需要以suffix结束的筛选条件。

+

idMatches(String)#

+
    +
  • String <string> id要满足的正则表达式
  • +
+

附加id需要满足正则表达式。有关正则表达式,可以查看菜鸟教程

+

这里的正则表达式是Java的正则表达式,不能直接使用JavaScript的正则表达式。

+
idMatches("[a-zA-Z]+")
+

text(str)#

+
+

附加控件文本等于字符串str的筛选条件。

+

控件的text(文本)属性是控件上的显示的文字,例如微信左上角的"微信"文本。对于图片或者其他控件通常text属性为null。

+

textContains(str)#

+
+

附加控件文本需要以prefix开头的筛选条件。

+

textStartsWith(prefix)#

+
+

附加控件文本需要以prefix开头的筛选条件。

+

textEndsWith(suffix)#

+
+

附加控件文本需要以suffix结束的筛选条件。

+

textMatches(str)#

+
    +
  • String <string> 要满足的正则表达式
  • +
+

附加控件文本需要满足正则表达式的条件。

+

desc(str)#

+
+

附加控件描述等于字符串str的筛选条件。

+

控件的desc(描述,全称为Content-Description)属性是对一个控件的描述,例如网易云音乐右上角的放大镜图标的描述为搜索。要查看一个控件的描述,同样地可以借助悬浮窗查看。

+

desc属性同样是定位控件的利器。

+

descContains(str)#

+
+

附加控件描述需要以prefix开头的筛选条件。

+

descStartsWith(prefix)#

+
+

附加控件描述需要以prefix开头的筛选条件。

+

descEndsWith(suffix)#

+
+

附加控件描述需要以suffix结束的筛选条件。

+

descMatches(str)#

+
    +
  • String <string> 要满足的正则表达式
  • +
+

附加控件描述需要满足正则表达式的条件。

+

className(str)#

+
+

附加控件类名等于字符串str的筛选条件。

+

控件的className属性是一个控件的具体类型,例如图片控件通常为ImageView,文本控件通常为TextView, 输入框通常为EditText。(若一个控件是在android.widget包里的,那么android.widget可以省略。但除此之外的其他控件必须是类的全名,例如"com.stardust.theme.ThemeColorImageView")。

+

classNameContains(str)#

+
+

附加控件类名需要以prefix开头的筛选条件。

+

classNameStartsWith(prefix)#

+
+

附加控件类名需要以prefix开头的筛选条件。

+

classNameEndsWith(suffix)#

+
+

附加控件类名需要以suffix结束的筛选条件。

+

classNameMatches(str)#

+
    +
  • String <string> 要满足的正则表达式
  • +
+

附加控件类名需要满足正则表达式的条件。

+

packageName(str)#

+
+

附加包名等于字符串str的筛选条件。

+

packageName属性也即控件所属的应用的包名(参见《shell命令:应用包名》),通常用来保证当前运行的应用是想要的应用。

+

packageNameContains(str)#

+
+

附加包名需要以prefix开头的筛选条件。

+

packageNameStartsWith(prefix)#

+
+

附加包名需要以prefix开头的筛选条件。

+

packageNameEndsWith(suffix)#

+
+

附加包名需要以suffix结束的筛选条件。

+

packageNameMatches(str)#

+
    +
  • String <string> 要满足的正则表达式
  • +
+

附加包名需要满足正则表达式的条件。

+

bounds(l, t, r, b)#

+
    +
  • l, t, r, b 用来定位控件在屏幕上的范围的四个整数
  • +
+

boundsInside(l, t, r, b)#

+

boundsContains(l, t, r, b)#

+

drawingOrder(order)#

+
    +
  • order <number> 控件在父视图中的绘制顺序,在一些
  • +
+

checkable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可勾选, 默认为true
  • +
+

附加控件是否可勾选的条件。可勾选指的是,例如QQ和微信发送图片时图片的勾选。

+

selected([b = true])#

+
    +
  • b <Boolean> 表示控件是否被选中,默认为true
  • +
+

附加控件是否被选中的条件。被选中指的是,例如QQ聊天界面点击下方的表情按钮时,会出现自己收藏的表情,这时表情按钮便处于选中状态。

+

clickable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可点击, 默认为true
  • +
+

附加控件是否可点击的条件。但并非所有clickable为false的控件都真的不能点击,这取决于控件的实现。因而要确定一个控件的clickable属性,可以开启悬浮窗工具。

+

longClickable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可长按, 默认为true
  • +
+

附加控件是否可长按的条件。

+

enabled([b = true])#

+
    +
  • b <Boolean> 表示控件是否已启用, 默认为true
  • +
+

附加控件是否已启用的条件。大多数控件都是启用的状态,处于“禁用”状态通常是灰色并且不可点击。

+

scrollable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可滑动, 默认为true
  • +
+

附加控件是否可滑动的条件。

+

editable([b = true])#

+
    +
  • b <Boolean> 表示控件是否可编辑, 默认为true
  • +
+

附加控件是否可编辑的条件。一般来说可编辑的控件为输入框(EditText)。

+

contentInvalid([b = true])#

+
    +
  • b <Boolean> 表示控件是否是contentInvalid, 默认为true
  • +
+

我也不知道是什么,下次再补充吧。

+

contextClickable([b = true])#

+
    +
  • b <Boolean> 表示控件是否是contextClickable, 默认为true
  • +
+

我也不知道是什么,下次再补充吧。

+

multiLine([b = true])#

+
    +
  • b <Boolean> 表示文本或输入框控件是否是多行显示的, 默认为true
  • +
+

附加控件是否文本或输入框控件是否是多行显示的条件。

+

findOne()#

+

根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到屏幕上出现满足条件的一个控件为止,并返回该控件。如果找不到控件,当屏幕内容发生变化时会重新寻找,直至找到。参见控件

+

find()#

+

根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,找到所有满足条件的控件集合并返回。这个搜索只进行一次,并不保证一直会找到,因而会出现返回的控件集合为空的情况。参见控件集合

+

可以通过empty()或nonEmpty()函数判断找到的是否为空。例如:

+
var c = className("AbsListView").find();
+if(c.empty()){
+    toast("找到啦");
+}else{
+    toast("没找到╭(╯^╰)╮");
+}
+

untilFind()#

+

根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到找到至少一个满足条件的控件为止,并返回所有满足条件的控件集合。参见控件集合

+

exists()#

+

判断屏幕上是否存在控件符合选择器所确定的条件。例如要判断某个文本出现就执行某个动作,可以用:

+
if(text("嘿嘿嘿").exists()){
+    //嘿嘿嘿
+}
+

waitFor()#

+

等待屏幕上出现符合条件的控件。

+
text("嘿嘿嘿").waitFor();
+

click()#

+

找到所有符合条件的控件并点击。相当于untilFind().click()。参见click)。

+

longClick()#

+

找到所有符合条件的控件并长按。相当于untilFind().longClick()。参见longClick)。

+

copy()#

+

找到所有符合条件的控件并复制其内容,只对文本框或输入框控件有文字选中时有效。相当于untilFind().copy()。参见copy)。

+

paste()#

+

找到所有符合条件的控件并粘贴,只对输入框控件有效。相当于untilFind().paste()。参见paste)。

+

select()#

+

找到所有符合条件的控件并选中。相当于untilFind().select()。参见select)。

+

cut()#

+

找到所有符合条件的控件并剪切其内容,只对文本框或输入框控件有文字选中时有效。相当于untilFind().cut()。参见cut)。

+

collapse()#

+

找到所有符合条件的控件并折叠。相当于untilFind().collapse()。参见collapse)。

+

expand()#

+

找到所有符合条件的控件并展开。相当于untilFind().expand()。参见expand)。

+

show()#

+

找到所有符合条件的控件并使其出现在屏幕上。相当于untilFind().show()。参见show)。

+

scrollForward()#

+

找到所有符合条件的控件并向前滑。相当于untilFind().scrollForward()。参见scrollForward)。
向前滑指的是,对于左右滑动的控件向右滑,上下滑动的控件向下滑。

+

scrollBackward()#

+

找到所有符合条件的控件并向后滑。相当于untilFind().scrollBackward()。参见scrollBackward)。
向后滑指的是,对于左右滑动的控件向左滑,上下滑动的控件向上滑。

+

scrollUp()#

+

找到所有符合条件的控件并向上滑。相当于untilFind().scrollUp()。参见scrollUp)。

+

scrollDown()#

+

找到所有符合条件的控件并向下滑。相当于untilFind().scrollDown()。参见scrollDown)。

+

scrollLeft()#

+

找到所有符合条件的控件并向左滑。相当于untilFind().scrollLeft()。参见scrollLeft)。

+

scrollRight()#

+

找到所有符合条件的控件并向右滑。相当于untilFind().scrollRight()。参见scrollRight)。

+

contextClick()#

+

文档缺失

+

setSelection(start, end)#

+
    +
  • start <number> 文字选中开始位置
  • +
  • end <number> 文字选中结束位置
  • +
+

找到所有符合条件的控件并设置文字选中区域,只对文本控件和输入框有效。相当于untilFind().setSelection()。参见setSelection

+

setText(text)#

+
    +
  • text <string> 要设置的文本 +找到所有符合条件的控件并设置文字,只对输入框有效。相当于untilFind().setText()。参见setText
  • +
+

UiCollection#

+

UiCollection, 控件集合, 通过选择器的find(), untilFind()方法返回的对象。可以对其进行操作或者获取其信息。

+

UiCollection.size()#

+

返回集合中的控件数。

+

UiCollection.get(i)#

+
+

返回集合中第i+1个控件(UiObject)。

+

UiCollection.each(func)#

+
    +
  • func \ 遍历函数
  • +
+

遍历集合。例如:

+
var c = clickable();
+c.each(function(o){
+    log(o.text());
+});
+

empty()#

+

返回控件集合是否为空。

+

nonEmpty()#

+

返回控件集合是否非空。

+

UiCollection.filter(filter)#

+
    +
  • filter \ 过滤函数。参数为UiObject,返回值为Boolean。
  • +
+

过滤出控件集合中符合条件的子控件。例如要过滤出所有子控件数目为1的控件为:

+
var newCollection = collection.filter(function(obj){
+    return obj.childCount() == 1;
+});
+

UiCollection.find(selector)#

+
    +
  • selector \ 选择器
  • +
+

根据selector所确定的条件在该控件集合的控件和子控件找到所有符合条件的控件并返回控件集合。

+

注意这会递归地遍历控件集合里所有的控件以及他们的子控件。和filter函数不同。

+

例如:

+
var names = id("name");
+var clickableNames = names.find(clickable());
+

UiCollection.findOne(selector)#

+
    +
  • selector \ 选择器
  • +
+

根据selector所确定的条件在该控件集合中找到一个符合条件的控件并返回控件。若找不到则返回null。

+

UiCollection.click()#

+

点击集合中所有控件,并返回是否全部点击成功。

+

UiCollection.longClick()#

+

长按集合中所有控件,并返回是否全部操作成功。

+

UiCollection.copy()#

+

对集合中所有控件执行复制操作,并返回是否全部操作成功。

+

UiCollection.paste()#

+

对集合中所有控件执行粘贴操作,并返回是否全部操作成功。

+

UiCollection.select()#

+

对集合中所有控件执行选中操作,并返回是否全部操作成功。

+

UiCollection.cut()#

+

对集合中所有控件执行剪切操作,并返回是否全部操作成功。

+

UiCollection.collapse()#

+

对集合中所有控件执行折叠操作,并返回是否全部操作成功。

+

UiCollection.expand()#

+

对集合中所有控件执行展开操作,并返回是否全部操作成功。

+

UiCollection.show()#

+

对集合中所有控件执行显示操作,并返回是否全部操作成功。

+

UiCollection.scrollForward()#

+

对集合中所有控件执行向前滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollBackward()#

+

对集合中所有控件执行向后滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollUp()#

+

对集合中所有控件执行向上滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollDown()#

+

对集合中所有控件执行向下滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollLeft()#

+

对集合中所有控件执行向左滑的操作,并返回是否全部操作成功。

+

UiCollection.scrollRight()#

+

对集合中所有控件执行向右滑的操作,并返回是否全部操作成功。

+

UiCollection.contextClick()#

+

UiCollection.setSelection(start, end)#

+
    +
  • start <number> 文字选中开始位置
  • +
  • end <number> 文字选中结束位置
  • +
+

对集合中所有控件设置文字选中区域,并返回是否全部操作成功。

+

UiCollection.setText(text)#

+
    +
  • text <string> 要设置的文本 +对集合中所有控件设置文本,并返回是否全部操作成功。
  • +
+

UiObject#

+

控件, 选择器的findOne方法返回的对象。和UiCollection有相似的方法,不再赘述。除此之外还有以下方法。

+

child(i)#

+
+

返回第i+1个子控件(UiObject)。

+

parent()#

+

返回父控件(UiObject)。

+

children()#

+

返回该控件的所有子控件组成的控件集合。

+

childCount()#

+

返回子控件数目。

+

bounds()#

+

返回控件在屏幕上的范围,其值是一个[Rect]对象。

+

boundsInParent()#

+

返回控件在父控件中的范围,其值是一个[Rect]对象。

+

drawingOrder()#

+

返回控件的绘制次序。

+

id()#

+

返回控件的id,可能为null。

+

text()#

+

返回控件的文本,如果控件没有文本,返回""。

+

findByText(text)#

+
+

根据文本text在子控件中递归地寻找并返回文本或描述(desc)包含这段文本text的控件,返回它们组成的集合。。

+

find(selector)#

+
    +
  • selector \ 选择器
  • +
+

根据选择器selector在子控件中递归地寻找符合条件的控件,返回它们组成的集合。

+

findOne#

+

find(selector)#

+
    +
  • selector \ 选择器
  • +
+

根据选择器selector在子控件中递归地寻找一个符合条件的控件。找不到则返回null。

+

Rect#

+

UiObject.bounds(), UiObject.boundsInParent()返回的对象。表示一个长方形。

+

Rect.left#

+

长方形左边界的x坐标、

+

Rect.right#

+

长方形左边界的x坐标、

+

Rect.top#

+

长方形上边界的y坐标、

+

Rect.bottom#

+

长方形下边界的y坐标、

+

Rect.centerX()#

+

长方形中点x坐标。

+

Rect.centerY()#

+

长方形中点y坐标。

+

Rect.width()#

+

长方形宽度。通常可以作为控件宽度。

+

Rect.height()#

+

长方形高度。通常可以作为控件高度。

+

Rect.contains(r)#

+
    +
  • r \
  • +
+

返回是否包含另一个长方形r。

+

Rect.intersect(r)#

+
    +
  • r \
  • +
+

返回是否和另一个长方形相交。

+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/assets/docs/work-with-java.html b/app/src/main/assets/docs/work-with-java.html new file mode 100644 index 00000000..3e3d2480 --- /dev/null +++ b/app/src/main/assets/docs/work-with-java.html @@ -0,0 +1,79 @@ + + + + + Index | Auto.js 2.0.16 文档 + + + + + + +
+
+ + +
+ + +
+ + + +
+ +
+
+

Auto.js 2.0.16 文档

+
+

+ 索引 | + 查看全部 +

+
+
+
+ +
+

目录

+ +
+ +
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/doc/OnlineDocsFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/doc/OnlineDocsFragment.java index 99ada24c..df466fdd 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/doc/OnlineDocsFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/doc/OnlineDocsFragment.java @@ -2,6 +2,7 @@ package com.stardust.scriptdroid.ui.doc; import android.app.Activity; import android.content.Context; +import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.Fragment; import android.support.v4.view.ViewPager; @@ -33,16 +34,19 @@ public class OnlineDocsFragment extends ViewPagerFragment implements BackPressed public OnlineDocsFragment() { super(ROTATION_GONE); + setArguments(new Bundle()); } @AfterViews void setUpViews() { mWebView = mEWebView.getWebView(); String url = Pref.getDocumentationUrl() + "index.html"; - if (getArguments() != null) { - url = getArguments().getString(ARGUMENT_URL, url); + Bundle savedWebViewState = getArguments().getBundle("savedWebViewState"); + if (savedWebViewState != null) { + mWebView.restoreState(savedWebViewState); + } else { + mWebView.loadUrl(getArguments().getString(ARGUMENT_URL, url)); } - mWebView.loadUrl(url); } @@ -57,6 +61,9 @@ public class OnlineDocsFragment extends ViewPagerFragment implements BackPressed @Override public void onPause() { super.onPause(); + Bundle savedWebViewState = new Bundle(); + mWebView.saveState(savedWebViewState); + getArguments().putBundle("savedWebViewState", savedWebViewState); ((BackPressedHandler.HostActivity) getActivity()) .getBackPressedObserver() .unregisterHandler(this); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java index f9cc2d53..6838cc9c 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java @@ -1,6 +1,8 @@ package com.stardust.scriptdroid.ui.main; import android.Manifest; +import android.app.SearchManager; +import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; @@ -10,17 +12,22 @@ import android.support.annotation.RequiresApi; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; +import android.support.v4.view.MenuItemCompat; import android.support.v4.view.ViewPager; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.widget.SearchView; import android.support.v7.widget.Toolbar; import android.view.Gravity; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import com.qq.e.comm.DownloadService; import com.stardust.app.FragmentPagerAdapterBuilder; import com.stardust.app.OnActivityResultDelegate; import com.stardust.enhancedfloaty.FloatyService; +import com.stardust.pio.PFile; import com.stardust.pio.PFiles; import com.stardust.scriptdroid.BuildConfig; import com.stardust.scriptdroid.Pref; @@ -43,11 +50,13 @@ import com.stardust.scriptdroid.ui.update.VersionGuard; import com.stardust.util.BackPressedHandler; import com.stardust.view.DrawerAutoClose; import com.stardust.widget.CommonMarkdownView; +import com.stardust.widget.SearchViewItem; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.Click; import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.ViewById; +import org.greenrobot.eventbus.EventBus; import java.util.Arrays; @@ -233,7 +242,6 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega return mActivityResultMediator; } - @Override public void onBackPressed() { if (!mBackPressObserver.onBackPressed(this)) { @@ -246,4 +254,25 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega return mBackPressObserver; } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_main, menu); + MenuItem searchMenuItem = menu.findItem(R.id.action_search); + setUpSearchMenuItem(searchMenuItem); + return true; + } + + private void setUpSearchMenuItem(MenuItem searchMenuItem) { + SearchViewItem searchViewItem = new SearchViewItem(this, searchMenuItem); + searchViewItem.setQueryCallback(this::submitQuery); + } + + private void submitQuery(String query) { + if (query == null) { + EventBus.getDefault().post(QueryEvent.CLEAR); + return; + } + EventBus.getDefault().post(new QueryEvent(query)); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/QueryEvent.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/QueryEvent.java new file mode 100644 index 00000000..7667b6bd --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/QueryEvent.java @@ -0,0 +1,20 @@ +package com.stardust.scriptdroid.ui.main; + +/** + * Created by Stardust on 2017/10/25. + */ + +public class QueryEvent { + + public static final QueryEvent CLEAR = new QueryEvent(null); + + private final String mQuery; + + public QueryEvent(String query) { + mQuery = query; + } + + public String getQuery() { + return mQuery; + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/ViewPagerFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/ViewPagerFragment.java index 1c8716df..e573c630 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/ViewPagerFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/ViewPagerFragment.java @@ -1,5 +1,6 @@ package com.stardust.scriptdroid.ui.main; +import android.support.annotation.CallSuper; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.Fragment; import android.support.v4.view.animation.FastOutSlowInInterpolator; @@ -15,12 +16,8 @@ public abstract class ViewPagerFragment extends Fragment { private int mFabRotation; private FloatingActionButton mFab; - private View.OnClickListener mOnFabClickListener = new View.OnClickListener() { - @Override - public void onClick(View v) { - onFabClick((FloatingActionButton) v); - } - }; + private boolean mShown; + private View.OnClickListener mOnFabClickListener = v -> onFabClick((FloatingActionButton) v); public ViewPagerFragment(int fabRotation) { mFabRotation = fabRotation; @@ -32,7 +29,9 @@ public abstract class ViewPagerFragment extends Fragment { protected abstract void onFabClick(FloatingActionButton fab); + @CallSuper public void onPageShow() { + mShown = true; if (mFabRotation == ROTATION_GONE) { if (mFab.getVisibility() == View.VISIBLE) { mFab.hide(); @@ -54,7 +53,12 @@ public abstract class ViewPagerFragment extends Fragment { } + @CallSuper public void onPageHide() { + mShown = false; + } + public boolean isShown() { + return mShown; } } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/community/CommunityFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/community/CommunityFragment.java index 083f26bd..2669e770 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/community/CommunityFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/community/CommunityFragment.java @@ -1,10 +1,14 @@ package com.stardust.scriptdroid.ui.main.community; import android.app.Activity; +import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.webkit.WebView; +import com.stardust.scriptdroid.Pref; import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.ui.main.QueryEvent; import com.stardust.scriptdroid.ui.main.ViewPagerFragment; import com.stardust.util.BackPressedHandler; import com.stardust.widget.EWebView; @@ -12,7 +16,10 @@ import com.stardust.widget.EWebView; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.ViewById; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import java.net.URLEncoder; import java.util.regex.Pattern; /** @@ -30,12 +37,25 @@ public class CommunityFragment extends ViewPagerFragment implements BackPressedH public CommunityFragment() { super(0); + setArguments(new Bundle()); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); } @AfterViews void setUpViews() { mWebView = mEWebView.getWebView(); - mWebView.loadUrl("http://www.autojs.org/"); + String url = "http://www.autojs.org/"; + Bundle savedWebViewState = getArguments().getBundle("savedWebViewState"); + if (savedWebViewState != null) { + mWebView.restoreState(savedWebViewState); + } else { + mWebView.loadUrl(url); + } } @Override @@ -49,6 +69,9 @@ public class CommunityFragment extends ViewPagerFragment implements BackPressedH @Override public void onPause() { super.onPause(); + Bundle savedWebViewState = new Bundle(); + mWebView.saveState(savedWebViewState); + getArguments().putBundle("savedWebViewState", savedWebViewState); ((BackPressedHandler.HostActivity) getActivity()) .getBackPressedObserver() .unregisterHandler(this); @@ -73,8 +96,24 @@ public class CommunityFragment extends ViewPagerFragment implements BackPressedH } } + @Subscribe + public void submitQuery(QueryEvent event) { + if (!isShown() || event == QueryEvent.CLEAR) { + return; + } + String query = URLEncoder.encode(event.getQuery()); + String url = String.format("http://www.autojs.org/search?term=%s&in=titlesposts", query); + mWebView.loadUrl(url); + } + private boolean isInPostsPage() { String url = mWebView.getUrl(); return url.matches(POSTS_PAGE_PATTERN); } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/MyScriptListFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/MyScriptListFragment.java index 5b41664d..e185bbd4 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/MyScriptListFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/MyScriptListFragment.java @@ -1,6 +1,8 @@ package com.stardust.scriptdroid.ui.main.scripts; import android.app.Activity; +import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.view.View; @@ -11,12 +13,15 @@ import com.stardust.scriptdroid.io.StorageFileProvider; import com.stardust.scriptdroid.tool.SimpleObserver; import com.stardust.scriptdroid.ui.common.ScriptOperations; import com.stardust.scriptdroid.ui.main.FloatingActionMenu; +import com.stardust.scriptdroid.ui.main.QueryEvent; import com.stardust.scriptdroid.ui.main.ViewPagerFragment; import com.stardust.util.BackPressedHandler; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.ViewById; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -37,15 +42,17 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress private FloatingActionMenu mFloatingActionMenu; + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + @AfterViews void setUpViews() { mScriptFileList.setStorageFileProvider(StorageFileProvider.getDefault()); - mScriptFileList.setOnScriptFileClickListener(new ScriptListView.OnScriptFileClickListener() { - @Override - public void onScriptFileClick(View view, ScriptFile file) { - Scripts.edit(file); - //EditorFloaty.floatingEdit(getContext(), file); - } + mScriptFileList.setOnScriptFileClickListener((view, file) -> { + Scripts.edit(file); }); } @@ -109,11 +116,25 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress @Override public void onPageHide() { + super.onPageHide(); if (mFloatingActionMenu != null && mFloatingActionMenu.isExpanded()) { mFloatingActionMenu.collapse(); } } + @Subscribe + public void onQuerySummit(QueryEvent event) { + if (!isShown()) { + return; + } + if (event == QueryEvent.CLEAR) { + mScriptFileList.setFilter(null); + return; + } + String query = event.getQuery(); + mScriptFileList.setFilter((file -> file.getSimplifiedName().contains(query))); + } + @Override public void onDetach() { super.onDetach(); @@ -121,6 +142,12 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress mFloatingActionMenu.setOnFloatingActionButtonClickListener(null); } + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + @Override public void onClick(FloatingActionButton button, int pos) { switch (pos) { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java index e83b37a0..79168b75 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java @@ -17,6 +17,7 @@ import android.widget.ImageView; import android.widget.PopupMenu; import android.widget.TextView; +import com.stardust.pio.PFile; import com.stardust.pio.PFiles; import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.model.script.ScriptFile; @@ -34,6 +35,7 @@ import butterknife.ButterKnife; import butterknife.OnClick; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; /** @@ -64,6 +66,7 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa private ScriptListAdapter mScriptListAdapter = new ScriptListAdapter(); private ScriptFile mCurrentDirectory; private OnScriptFileClickListener mOnScriptFileClickListener; + private Function mFilter; private OnItemOperatedListener mOnItemOperatedListener; private ScriptFile mSelectedScriptFile; private StorageFileProvider mStorageFileProvider; @@ -126,6 +129,15 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa mDirectorySpanSize = directorySpanSize; } + public void setFilter(Function filter) { + mFilter = filter; + reload(); + } + + public void reload() { + loadScriptList(); + } + private void init() { setOnRefreshListener(this); mScriptListView = new RecyclerView(getContext()); @@ -160,6 +172,7 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa setRefreshing(true); mStorageFileProvider.getDirectoryFiles(mCurrentDirectory) .subscribeOn(Schedulers.io()) + .filter(f -> mFilter == null ? true : mFilter.apply(f)) .collectInto(mScriptList.cloneConfig(), (list, file) -> list.add(new ScriptFile(file)) ) diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java index a6ffb718..25eeb875 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java @@ -1,5 +1,6 @@ package com.stardust.scriptdroid.ui.main.task; +import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.v4.widget.SwipeRefreshLayout; import android.view.MenuItem; @@ -50,6 +51,7 @@ public class TaskManagerFragment extends ViewPagerFragment implements PopupMenu. public TaskManagerFragment() { super(45); + setArguments(new Bundle()); } @@ -60,6 +62,9 @@ public class TaskManagerFragment extends ViewPagerFragment implements PopupMenu. mNoRunningScriptNotice.setVisibility(noRunningScript ? View.VISIBLE : View.GONE); mStardustConsole = (StardustConsole) AutoJs.getInstance().getGlobalConsole(); mConsoleView.setConsole(mStardustConsole); + if (getArguments().getBoolean("console_shown", false)) { + showLog(); + } } private void init() { @@ -104,6 +109,7 @@ public class TaskManagerFragment extends ViewPagerFragment implements PopupMenu. return true; } + private void showLog() { mTaskManagerView.setVisibility(View.GONE); mConsoleView.setVisibility(View.VISIBLE); @@ -125,4 +131,10 @@ public class TaskManagerFragment extends ViewPagerFragment implements PopupMenu. AutoJs.getInstance().getScriptEngineService().stopAll(); } } + + @Override + public void onPause() { + super.onPause(); + getArguments().putBoolean("console_shown", mConsoleView.getVisibility() == View.VISIBLE); + } } diff --git a/app/src/main/java/com/stardust/widget/SearchViewItem.java b/app/src/main/java/com/stardust/widget/SearchViewItem.java new file mode 100644 index 00000000..fb1fc0fa --- /dev/null +++ b/app/src/main/java/com/stardust/widget/SearchViewItem.java @@ -0,0 +1,72 @@ +package com.stardust.widget; + +import android.app.Activity; +import android.app.SearchManager; +import android.content.Context; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.widget.SearchView; +import android.view.MenuItem; + +import com.stardust.scriptdroid.ui.main.MainActivity; + +/** + * Created by Stardust on 2017/10/25. + */ + +public class SearchViewItem implements MenuItemCompat.OnActionExpandListener, SearchView.OnQueryTextListener { + + public interface QueryCallback { + void summitQuery(String query); + } + + private QueryCallback mQueryCallback; + private MenuItem mSearchMenuItem; + + public SearchViewItem(Activity activity, MenuItem searchMenuItem) { + mSearchMenuItem = searchMenuItem; + SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE); + SearchView searchView = (SearchView) searchMenuItem.getActionView(); + if (searchView == null) { + return; + } + searchView.setSearchableInfo(searchManager.getSearchableInfo(activity.getComponentName())); + MenuItemCompat.setOnActionExpandListener(searchMenuItem, this); + searchView.setOnQueryTextListener(this); + } + + public void setQueryCallback(QueryCallback queryCallback) { + mQueryCallback = queryCallback; + } + + public void setVisible(boolean visible) { + mSearchMenuItem.setVisible(visible); + } + + @Override + public boolean onMenuItemActionExpand(MenuItem item) { + return true; + } + + @Override + public boolean onMenuItemActionCollapse(MenuItem item) { + if (mQueryCallback == null) { + return true; + } + mQueryCallback.summitQuery(null); + return true; + } + + @Override + public boolean onQueryTextSubmit(String query) { + if (mQueryCallback == null) { + return true; + } + mQueryCallback.summitQuery(query); + return true; + } + + @Override + public boolean onQueryTextChange(String newText) { + return false; + } +} diff --git a/app/src/main/res/drawable/ic_search_white_36dp.png b/app/src/main/res/drawable/ic_search_white_36dp.png new file mode 100644 index 0000000000000000000000000000000000000000..4f6f6075b562ea2a35908e7982b4c39bb31dcf34 GIT binary patch literal 1119 zcmV-l1fctgP)+}4U z=iQ!f&exfHXYS0E9LI4S$8j9TaU92S9LE__Leql4QAu->&Ptk=bW+l!qzOsSByC7q zl5}6v50Vx_27Jxj#V7oPq$x?KC7qM>uB0O+xmG33gb*GM-tr*?c!~01z6M+X4phu}0JsP| zD#^RZsNGX3e*j$t4h@+5FmSCT|CPFHY7OGl$YKZhv?iVTPCiTLOdUF{L-9Pb7BjoF z<_om$)Tz}9#1)Xm)l8a2!+$P^W@8YSlf77DzVHsTA3d8=~Eh+FN-PO70NjrhI9yj8JutafE5)zC>JzM7b~Dt{Vrt6kYidN~4Y ztM@e*4Dk>`FCGDhGigo&e;K;ga&&(HoHq&s_&Ss3HwBt+ z=g@2v;Fp2|=WEvbtU&8_om#B{%uu}7Q;Vq`GcBEM;Eg(Th63R8f}R6$+hU-5D)F9K zG|T}m*IiSq5T`MVB}G3bzG<(thu+C~3Ht%`oV#S6rnLfaoOnE@j1AyR;3HrfI0TFl z_ur?1kAbhS=b5{?1~h)wwGn_*6-~{>AH*X;qXV(0mJR<@?qY8zuZ*IpC;< zwt>sUb5Eh*y5*5GRg!=+z@3`Ryv?quQOWhojOrOuU=FxJTx<8kCU6sD1w_1O4vnd8 zdM$t0C3Dr zt(l6Z{$7WvsRteQ1)Z<#W@VpraR#B&Qy=8&o&QUKsa>YJnW=P{>SoqO$5c1daU92S l9LI4S$8j9TaU5qr{sYYg?x7SQVH^Me002ovPDHLkV1fV&5TXD8 literal 0 HcmV?d00001 diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml new file mode 100644 index 00000000..bdf33d43 --- /dev/null +++ b/app/src/main/res/menu/menu_main.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e9f67f5a..399a7a07 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -262,6 +262,7 @@ 打包中 清理临时文件 脚本文件路径 + 搜索 diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java index 3dab785d..c2762975 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java @@ -18,6 +18,7 @@ import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.commonjs.module.RequireBuilder; import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider; +import org.mozilla.javascript.tools.debugger.Dim; import java.io.File; import java.io.IOException;