上一回实现了一个插件的皮毛,本打算兼并火狐浏览器的GeckoView,作为webview的又一个可选替代,但没能成功,加载动态库时总是失败。怪只怪功力不够深厚。最近又要给tesseract做一个插件,作为安卓的文本识别之心。需小试一番,记录如下。
上一篇 > 巧用createPackageContext,实现插件化
Github : Plugin101、Plugin Invoker 101
共享 Tesseract 动态库
介绍安卓webview的加载机制,没看懂,只看明白“只要是库APP中的类,就可以像往常一样加载动态库”, so easy。
这个Tesseract Android版本通过maven { url "https://jitpack.io" }
、api 'cz.adaptech:tesseract4android:4.1.1'
提供了编译好的库(也可自行编译),在插件项目中直接引用,测试识别处于 raw 目录下的图片文件。调用者无需集成Tesseract的Java/c++代码即可拥有高大上的OCR光学识别能力。
public class TesseractPluginTest { ...
public static void Test(Context context) {
//CMN.rt();
TessBaseAPI tess = new TessBaseAPI();
String dataPath = new File(Environment.getExternalStorageDirectory(), "tesseract").getAbsolutePath();
tess.init(dataPath, "eng");
tess.setImage(getBitmapFromAsset(context, R.raw.text));
String text = tess.getUTF8Text(); // 纯文本
String textFormatted = tess.getHOCRText(0); // OCR标记html,每个单词隔开,各种信息
//CMN.pt("test_done", text); // 总共需要一秒不到的时间,不快不慢
Toast.makeText(context, text, 1).show();
tess.recycle();
}
复制代码
美中的不足是模型文件需要自己下载然后放到sd卡,这意味着调用者需要sd卡的读写权限,其实可以避免 ——
通过 contentProvider 共享私有目录的文件
参考:(其代码…总是胡乱换行,是不是屏幕太小了,或者不知道有个快捷键叫做Shift + 鼠标滚轮
?)
写在插件里的 ContentProvider :
public class PluginFileProvider extends ContentProvider {...
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
//CMN.Log("PluginFileProvider_openFile::", uri);
File file = new File(getContext().getExternalFilesDir(null), uri.getPath());
if (file.exists()) {
//CMN.Log("PluginFileProvider_openFile::exists");
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
//CMN.Log("PluginFileProvider_openFile::not exist!!");
throw new FileNotFoundException(uri.getPath());
}
复制代码
需在清单文件中注册:(其中name是实现类的路径,authorities是uri的getAuthority
,中文不知道怎么说,主域名?)
<application ...
<provider
android:name="com.knziha.plugin101.PluginFileProvider"
android:authorities="com.knziha.plugin101"
android:exported="true" >
</provider>
复制代码
测试项目以只读方式共享了sd卡外部私有目录getExternalFilesDir
(/sdcard/Android/data/…)下的data.txt。调用者无需获取整个sd卡的读写权限,即可访问并读取插件私有目录下data.txt中的内容。Tesseract的模型文件可以下载或者解压到这个目录中,会随插件的卸载而自动删除。
public class PrivatePathTest { ...
public static void Test(Context context) {
try {
//File dataFile = new File(context.getExternalFilesDir(null), "data.txt");
//FileInputStream fint = new FileInputStream(dataFile);//不行
//FileInputStream fin = context.openFileInput(dataFile.getName()); //不行
//fin.getFD()
Uri uri = Uri.parse("content://com.knziha.plugin101/data.txt");
InputStream fin = context.getContentResolver().openInputStream(uri);
byte[] data=new byte[512];
int len=fin.read(data);
fin.close();
//CMN.Log("PrivatePathTest::", new String(data, 0, len));
} catch (Exception e) {
//CMN.Log(e);
}
}
复制代码
下一步是实现图文之心插件 —— Tesseraction
未完待续……