插件 - Plugins
# 插件
Auto.js提供了加载插件的机制,允许用户编写带有Activity, Service, C/C++库等的apk,安装到Android设备上,并用Auto.js加载和调用。
一个插件是一个可独立安装的apk文件,用户安装后,再通过`$plugins`模块加载插件和调用其中的API。
## $plugins.load(packageName)
* `packageName` {string} 加载的插件包名
加载一个插件,并返回插件模块中module.exports导出的对象。
如果插件未安装,则抛出`PluginLoadException`异常。
以下为一个OCR插件的使用例子:(插件下载地址参见[OCR插件](#ocr插件))
```javascript
requestScreenCapture();
let OCR = $plugins.load('org.autojs.plugin.ocr');
let ocr = new OCR();
// 截取屏幕并对屏幕文字进行识别,返回识别结果
console.log(ocr.ocrScreen());
```
## 如何开发一个插件
> 以下示例代码可在这里找到完整项目:[插件SDK](https://github.com/hyb1996/Auto.js-Plugin-SDK)
本示例中的包名均为`org.autojs.plugin.sdk.demo`,在实际项目中插件包名可能有所不同。
### 插件SDK集成
新建一个Android项目,在项目的build.gradle文件中添加:
```groovy
allprojects {
repositories {
// ...
maven { url 'https://jitpack.io' }
}
}
```
在具体模块(比如app)的build.gradle文件中添加:
```groovy
dependencies {
// ...
implementation 'com.github.hyb1996:Auto.js-Plugin-SDK:0.2'
}
```
更多信息参见[Jitpack.io](https://jitpack.io/#hyb1996/Auto.js-Plugin-SDK/0.2)。
### 插件配置
#### 1. 新建`PluginHelloWorld`文件,继承于Plugin.
```java
public class PluginHelloWorld extends Plugin {
public PluginHelloWorld(Context context, Context selfContext, Object runtime, Object topLevelScope) {
super(context, selfContext, runtime, topLevelScope);
}
// 返回插件的JavaScript胶水层代码的assets目录路径
@Override
public String getAssetsScriptDir() {
return "plugin-helloworld";
}
// 插件public API,可被JavaScript代码调用
public String getStringFromJava() {
return "Hello, Auto.js!";
}
// 插件public API,可被JavaScript代码调用
public void say(String message) {
getSelfContext().startActivity(new Intent(getSelfContext(), HelloWorldActivity.class)
.putExtra("message", message)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}
```
#### 2. 新增`MyPluginRegistry`文件,继承于PluginRegistry:
```java
public class MyPluginRegistry extends PluginRegistry {
static {
// 注册默认插件
registerDefaultPlugin(new PluginLoader() {
@Override
public Plugin load(Context context, Context selfContext, Object runtime, Object topLevelScope) {
return new PluginHelloWorld(context, selfContext, runtime, topLevelScope);
}
});
}
}
```
在AndroidManifest.xml中配置以下meta-data, `name`为`"org.autojs.plugin.sdk.registry"`,`value`为MyPluginRegistry的包名。
```xml
<application
...>
<meta-data
android:name="org.autojs.plugin.sdk.registry"
android:value="org.autojs.plugin.sdk.demo.MyPluginRegistry" />
<activity
android:name=".HelloWorldActivity"
android:exported="true" />
<service
android:name=".HelloworldPluginService"
android:exported="true" />
</application>
```
#### 3. 编写JavaScript胶水层
在assets的相应目录(由Plugin.getAssetsScriptDir返回)中添加`index.js`文件,用于作为胶水层导出插件API。
```javascript
module.exports = function (plugin) {
let runtime = plugin.runtime;
let scope = plugin.topLevelScope;
function helloworld() {
}
helloworld.stringFromJava = plugin.getStringFromJava();
helloworld.say = function (message) {
plugin.say(message);
}
return helloworld;
}
```
#### 4. 在Auto.js Pro中调用
编译插件为apk(assembleDebug/assembleRelease),安装到设备上。在Auto.js Pro中使用以下代码调用:
```javascript
let helloworld = $plugins.load("org.autojs.plugin.sdk.demo");
console.log(helloworld.stringFromJava);
helloworld.say("Hello, Auto.js Pro Plugin");
```
#### 5. 独立服务AIDL方式调用
可以在插件中编写一个`Service`,由Auto.js Pro唤起和绑定,并可在js中通过aidl调用Service的接口。
在Plugin中重写方法`getService`。
```java
// 插件服务类,可选,用于AIDL方式和Auto.js Pro本体通信。可返回null
@Override
public ComponentName getService() {
return new ComponentName(getSelfContext().getPackageName(), HelloworldPluginService.class.getName());
}
```
新建一个Service组件(**注意在AndroidManifest中注册时需要是exported="true"**),继承于`PluginService`。
```java
public class HelloworldPluginService extends PluginService {
private static final String ACTION_ADD = "add";
@Override
protected Result onRemoteCall(@NonNull String action, @NonNull Map<String, Object> args, @Nullable RemoteCallback callback) throws RuntimeException {
switch (action) {
case ACTION_ADD:
return invokeAdd(args);
}
return Result.notImplemented(action);
}
private Result invokeAdd(Map<String, Object> args) {
Number a = PluginUtils.getNotNull(args, "a");
Number b = PluginUtils.getNotNull(args, "b");
double sum = a.doubleValue() + b.doubleValue();
return new Result(Collections.singletonMap("sum", sum));
}
}
```
在index.js中添加胶水层代码:
```javascript
helloworld.remoteAdd = function (a, b) {
return plugin.waitForConnection().call('add', {
a: a,
b: b
}, null).get('sum');
}
```
然后可以在Auto.js Pro中调用:
```javascript
let helloworld = $plugins.load("org.autojs.plugin.sdk.demo");
console.log(helloworld.remoteAdd(1, 2));
```
## OCR插件
目前Auto.js官方仅提供一个简单的OCR插件作为示例,其效率相对较慢,仅为参考。
[OCR插件下载](https://wws.lanzoux.com/iOfyWlpz7jc)(**密码: 4fw3**)
### new OCR([dataFile, lang])
* `dataFile` {string} 数据路径
* `lang` {string} 语言
创建一个新的OCR对象。OCR插件使用Tesseract为引擎。构造函数的dataFile和lang参数用于使用指定的语言模型初始化Tesseract引擎。
数据路径`dataFile`必须是tessdata的父目录的路径,并且必须以/结尾。最后一个/之后的任何路径都将被忽略。
要加载多种语言,例如,`hin + eng`将加载北印度语和英语。
更多信息参见[TessBaseAPI](https://github.com/rmtheis/tess-two/blob/master/tess-two/src/com/googlecode/tesseract/android/TessBaseAPI.java)。
使用自带的中文字库数据初始化OCR:
```javascript
let OCR = $plugins.load('org.autojs.plugin.ocr');
let ocr = new OCR();
```
使用自己的数据初始化OCR:
```javascript
let OCR = $plugins.load('org.autojs.plugin.ocr');
let ocr = new OCR("/sdcard/tessdata/", "chi_sim");
```
### OCR.ocrFile(path)
* `path` {string} 文件路径
* 返回 [OcrResult](#ocrresult)
对图片文件path进行OCR识别,返回识别后的结果。
```javascript
let OCR = $plugins.load('org.autojs.plugin.ocr');
let ocr = new OCR();
$events.on('exit', () => {
ocr.end();
});
let result = ocr.ocrFile($file.path('./image.png'));
console.log(result);
```
### OCR.ocrImage(img)
* `img` {Image} Auto.js的图片对象,通过·$images·模块截图或者读取文件返回的对象
* 返回 [OcrResult](#ocrresult)
对图片img进行OCR识别,返回识别后的结果。
```javascript
requestScreenCapture();
let OCR = $plugins.load('org.autojs.plugin.ocr');
let ocr = new OCR();
$events.on('exit', () => {
ocr.end();
});
let result = ocr.ocrImage(captureScreen());
console.log(result);
```
### OCR.ocrScreen()
* 返回 [OcrResult](#ocrresult)
截取当前屏幕进行OCR识别,返回识别后的结果。需要先申请截图权限。
### OCR.ocrBitmap(bitmap)
* `bitmap` {Bitmap} android.graphics.Bitmap对象
* 返回 [OcrResult](#ocrresult)
对图片bitmap进行OCR识别,返回识别后的结果。
### OCR.end()
结束OCR识别,回收相应的OCR对象。
### OcrResult
OCR识别返回的结果,有以下只读属性:
* `success` {boolean} 是否识别成功
* `text` {string} 识别文本信息
* `words` {[OcrWord](#ocrword)} 识别文本的列表(java.util.List对象)
* `timeRequired` {number} 识别耗时
### OcrWord
OCR识别中的文本。有以下只读属性:
* `text` {string} 识别的文本
* `bounds` {Rect} [android.graphics.Rect](https://developer.android.google.cn/reference/android/graphics/Rect)对象,表示文本在图片中的位置和范围
* `confidences` {number} 0~1之间的浮点数,表示结果的可信度,数值越大结果越可靠
## 第三方插件
参见章节[第三方插件](/zh-cn/thirdPartyPlugins)。