脚本引擎 - Engines

# Engines > Stability: 2 - Stable engines模块包含了一些与脚本环境、脚本运行、脚本引擎有关的函数,包括运行其他脚本,关闭脚本等。 例如,获取脚本所在目录: ``` toast(engines.myEngine().cwd()); ``` ## 运行脚本代码 | engines.execScript(name,script,config) | 函数名 | 返回值 | 备注 | | -------------------- | :-----------------: | ------------------------------------------------------------ | | engines.execScript() | ScriptExectuion对象 | 在新的脚本环境中运行脚本script。 | | **参数名** | **类型** | | | name | 字符串 | 要运行的脚本名称。这个名称和文件名称无关,只是在任务管理中显示的名称。 | | script | 字符串 | 要运行的脚本内容。 | | config | Object | 运行配置项 | engines.execScript(name, script[, config]) * `name` {string} 要运行的脚本名称。这个名称和文件名称无关,只是在任务管理中显示的名称。 * `script` {string} 要运行的脚本内容。 * `config` {Object} 运行配置项 * `delay` {number} 延迟执行的毫秒数,默认为0 * `loopTimes` {number} 循环运行次数,默认为1。0为无限循环。 * `interval` {number} 循环运行时两次运行之间的时间间隔,默认为0 * `path` {Array} | {string} 指定脚本运行的目录。这些路径会用于require时寻找模块文件。 在新的脚本环境中运行脚本script。返回一个[ScriptExecution](#engines_scriptexecution)对象。 所谓新的脚本环境,指定是,脚本中的变量和原脚本的变量是不共享的,并且,脚本会在新的线程中运行。 最简单的例子如下: ``` engines.execScript("hello world", "toast('hello world')"); ``` 如果要循环运行,则: ``` //每隔3秒运行一次脚本,循环10次 engines.execScript("hello world", "toast('hello world')", { loopTimes: 10, interval: 3000 }); ``` 用字符串来编写脚本非常不方便,可以结合 `Function.toString()`的方法来执行特定函数: ``` function helloWorld(){ //注意,这里的变量和脚本主体的变量并不共享 toast("hello world"); } engines.execScript("hello world", "helloWorld();\n" + helloWorld.toString()); ``` 如果要传递变量,则可以把这些封装成一个函数: ``` function exec(action, args){ args = args || {}; engines.execScript(action.name, action.name + "(" + JSON.stringify(args) + ");\n" + action.toString()); } //要执行的函数,是一个简单的加法 function add(args){ toast(args.a + args.b); } //在新的脚本环境中执行 1 + 2 exec(add, {a: 1, b:2}); ``` ## 运行脚本文件 | engines.execScriptFile(path,config) | 函数名 | 返回值 | 备注 | | ------------------------ | :-----------------: | ---------------------------------- | | engines.execScriptFile() | ScriptExectuion对象 | 在新的脚本环境中运行脚本文件path。 | | **参数名** | **类型** | | | path | 字符串 | 要运行的脚本路径。 | | config | Object | 运行配置项 | engines.execScriptFile(path[, config]) * `path` {string} 要运行的脚本路径。 * `config` {Object} 运行配置项 * `delay` {number} 延迟执行的毫秒数,默认为0 * `loopTimes` {number} 循环运行次数,默认为1。0为无限循环。 * `interval` {number} 循环运行时两次运行之间的时间间隔,默认为0 * `path` {Array} | {string} 指定脚本运行的目录。这些路径会用于require时寻找模块文件。 在新的脚本环境中运行脚本文件path。返回一个[ScriptExecution](#ScriptExecution)对象。 ``` engines.execScriptFile("/sdcard/脚本/1.js"); ``` ## 运行录制脚本 | engines.execAutoFile(path,config) | 函数名 | 返回值 | 备注 | | ---------------------- | :-----------------: | ---------------------------------- | | engines.execAutoFile() | ScriptExectuion对象 | 在新的脚本环境中运行录制文件path。 | | **参数名** | **类型** | | | path | 字符串 | 要运行的录制文件路径。 | | config | Object | 运行配置项 | engines.execAutoFile(path[, config]) * `path` {string} 要运行的录制文件路径。 * `config` {Object} 运行配置项 * `delay` {number} 延迟执行的毫秒数,默认为0 * `loopTimes` {number} 循环运行次数,默认为1。0为无限循环。 * `interval` {number} 循环运行时两次运行之间的时间间隔,默认为0 * `path` {Array} | {string} 指定脚本运行的目录。这些路径会用于require时寻找模块文件。 在新的脚本环境中运行录制文件path。返回一个[ScriptExecution](#ScriptExecution)对象。 ``` engines.execAutoFile("/sdcard/脚本/1.auto"); ``` ## 停止所有脚本 | engines.stopAll() | 函数名 | 返回值 | 备注 | | ----------------- | :----: | ------------------------------------------ | | engines.stopAll() | | 停止所有正在运行的脚本。包括当前脚本自身。 | engines.stopAll() 停止所有正在运行的脚本。包括当前脚本自身。 ## 停止所有脚本显示数量 | engines.stopAllAndToast() | 函数名 | 返回值 | 备注 | | ------------------------- | :----: | ------------------------------------------------------------ | | engines.stopAllAndToast() | | 停止所有正在运行的脚本并显示停止的脚本数量。包括当前脚本自身。 | engines.stopAllAndToast() 停止所有正在运行的脚本并显示停止的脚本数量。包括当前脚本自身。 ## 获取脚本引擎对象 | engines.myEngine() | 函数名 | 返回值 | 备注 | | ------------------ | :--------------: | -------------------------------------- | | engines.myEngine() | ScriptEngine对象 | 返回当前脚本的脚本引擎对象ScriptEngine | engines.myEngine() 返回当前脚本的脚本引擎对象([ScriptEngine](#engines?id=scriptengine)) **[v4.1.0新增]** 特别的,该对象可以通过`execArgv`来获取他的运行参数,包括外部参数、intent等。例如: ``` log(engines.myEngine().execArgv); ``` 普通脚本的运行参数通常为空,通过定时任务的广播启动的则可以获取到启动的intent。 ## 获取所有运行脚本引擎对象 | engines.all() | 函数名 | 返回值 | 备注 | | ------------- | :------------------: | -------------------------------------------------------- | | engines.all() | ScriptEngine对象数组 | 返回当前所有正在运行的脚本的脚本引擎ScriptEngine的数组。 | engines.all() * 返回 {Array} 返回当前所有正在运行的脚本的脚本引擎[ScriptEngine](#engines_scriptengine)的数组。 ``` log(engines.all()); ``` ## engines.startFloatingController(path[, config, options]) [Pro 9.1.10新增] | 函数名 | 返回值 | 备注 | | ------------ | -------- | -------------------- | | engines.startFloatingController() | 布尔型 | 通过应用包名启动应用 | | **参数名** | **类型** | | |path|string|要运行的脚本路径。| |config|Object|运行配置项,可选| |delay|number|延迟执行的毫秒数,默认为0| |loopTimes|number|循环运行次数,默认为1。0为无限循环。| |interval|number|循环运行时两次运行之间的时间间隔,默认为0| |path|Array|||string|指定脚本运行的目录。这些路径会用于require时寻找模块文件。| |options|Object|悬浮控制器选项,可选| |runImmediately|boolean|是否立即启动脚本引擎| 启动一个悬浮控制器(带有启动、暂停、日志等按钮),用于控制给定路径的脚本引擎的启动和停止。 # ScriptExecution 执行脚本时返回的对象,可以通过他获取执行的引擎、配置等,也可以停止这个执行。 要停止这个脚本的执行,使用`execution.getEngine().forceStop()`. ## 获取执行脚本引擎对象 | ScriptExecution.getEngine() | 函数名 | 返回值 | 备注 | | --------------------------- | :--------------: | ---------------------------------------- | | ScriptExecution.getEngine() | ScriptEngine对象 | 返回执行该脚本的脚本引擎对象ScriptEngine | ScriptExecution.getEngine() 返回执行该脚本的脚本引擎对象([ScriptEngine](#engines?id=scriptengine)) ## 获取脚本配置 | ScriptExecution.getConfig() | 函数名 | 返回值 | 备注 | | --------------------------- | :----------: | -------------------------------- | | ScriptExecution.getConfig() | ScriptConfig | 返回该脚本的运行配置ScriptConfig | ScriptExecution.getConfig() 返回该脚本的运行配置([ScriptConfig](#engines?id=scriptconfig)) # ScriptEngine 脚本引擎对象。 ## 停止脚本引擎的执行 | ScriptEngine.forceStop() | 函数名 | 返回值 | 备注 | | ------------------------ | :----: | -------------------- | | ScriptEngine.forceStop() | | 停止脚本引擎的执行。 | ScriptEngine.forceStop() 停止脚本引擎的执行。 ## 停止脚本引擎的执行 | ScriptEngine.cwd() | 函数名 | 返回值 | 备注 | | ------------------ | :----: | ------------------------------------------------------------ | | ScriptEngine.cwd() | 字符串 | 返回脚本执行的路径。对于一个脚本文件而言为这个脚本所在的文件夹;对于其他脚本,例如字符串脚本,则为`null`或者执行时的设置值。 | ScriptEngine.cwd() * 返回 {string} 返回脚本执行的路径。对于一个脚本文件而言为这个脚本所在的文件夹;对于其他脚本,例如字符串脚本,则为`null`或者执行时的设置值。 ## 获取脚本引擎脚本对象 | ScriptEngine.getSource() | 函数名 | 返回值 | 备注 | | ------------------------ | :----------: | ------------------------------------ | | ScriptEngine.getSource() | ScriptSource | 返回当前脚本引擎正在执行的脚本对象。 | ScriptEngine.getSource() * 返回 [ScriptSource](#engines_scriptsource) 返回当前脚本引擎正在执行的脚本对象。 ``` log(engines.myEngine().getSource()); ``` ## 向该脚本引擎发送一个事件 | ScriptEngine.emit(eventName,args) | 函数名 | 返回值 | 备注 | | ------------------- | :----------: | ------------------------------------------------------------ | | ScriptEngine.emit() | ScriptSource | 向该脚本引擎发送一个事件,该事件可以在该脚本引擎对应的脚本的events模块监听到并在脚本主线程执行事件处理。 | | **参数名** | **类型** | | | eventName | 字符串 | 事件名称 | | args | any | 事件参数 | ScriptEngine.emit(eventName[, ...args]) * `eventName` {string} 事件名称 * `...args` {any} 事件参数 向该脚本引擎发送一个事件,该事件可以在该脚本引擎对应的脚本的events模块监听到并在脚本主线程执行事件处理。 例如脚本receiver.js的内容如下: ``` //监听say事件 events.on("say", function(words){ toastLog(words); }); //保持脚本运行 setInterval(()=>{}, 1000); ``` 同一目录另一脚本可以启动他并发送该事件: ``` //运行脚本 var e = engines.execScriptFile("./receiver.js"); //等待脚本启动 sleep(2000); //向该脚本发送事件 e.getEngine().emit("say", "你好"); ``` # ScriptConfig 脚本执行时的配置。 ## 延迟执行的毫秒数 | delay() | 配置名 | 类型 | 备注 | | ------ | :----: | ---------------- | | delay | 整数型 | 延迟执行的毫秒数 | delay * {number} 延迟执行的毫秒数 ## 循环运行间隔 | interval() | 配置名 | 类型 | 备注 | | -------- | :----: | -------------------------------- | | interval | 整数型 | 循环运行时两次运行之间的时间间隔 | interval * {number} 循环运行时两次运行之间的时间间隔 ## 循环运行次数 | loopTimes() | 配置名 | 类型 | 备注 | | --------- | :----: | ------------ | | loopTimes | 整数型 | 循环运行次数 | loopTimes * {number} 循环运行次数 ## 获取模块路径数组 | getPath() | 配置名 | 返回值 | 备注 | | ------- | :----: | ------------------------------------------------ | | getPath | Array | 返回一个字符串数组表示脚本运行时模块寻找的路径。 |" getPath() * 返回 {Array} 返回一个字符串数组表示脚本运行时模块寻找的路径。 # 示例 ## 停止所有正在运行的脚本 ```js engines.stopAllAndToast(); ``` ## 运行脚本文件 ```js var scriptsPath = "/sdcard/脚本/"; if(!files.exists(scriptsPath)){ scriptsPath = "/sdcard/Scripts/"; } var scriptFiles = files.listDir(scriptsPath, function(name){ return name.endsWith(".js"); }); var i = dialogs.singleChoice("请选择要运行的脚本", scriptFiles); if(i < 0){ exit(); } var path = files.join(scriptsPath, scriptFiles[i]); engines.execScriptFile(path); ``` ## 运行录制文件 ```js var scriptsPath = "/sdcard/脚本/"; if(!files.exists(scriptsPath)){ scriptsPath = "/sdcard/Scripts/"; } var scriptFiles = files.listDir(scriptsPath, function(name){ return name.endsWith(".auto"); }); var i = dialogs.singleChoice("请选择要运行的脚本", scriptFiles); if(i < 0){ exit(); } var path = files.join(scriptsPath, scriptFiles[i]); engines.execAutoFile(path); ``` ## 运行新的脚本任务 ```js var script = "toast('Hello, Auto.js');" + "sleep(3000);" + "toast('略略略');"; var execution = engines.execScript("Hello", script); sleep(1000); execution.getEngine().forceStop(); ```