插件的管理,加载机制
插件的管理加载主要涉及以下几个类:
- pluginEntry.java
- ConfigXmlParser.java
- CordovaPlugin.java
- PluginManager.java
- PluginResult.java
以下分别对该类做说明
pluginEntry.java
顾名思义插件条目 该类用来保存插件的服务名和该服务名对应的插件类
比如camera插件对应的服务名为'Camera',对应的类名名为 'org.apache.cordova.camera.CameraLauncher'
之后需要加载插件的时候可以通过插件类名来动态生成该插件实例
ConfigXmlParser.java
该文件的作用是用来解析config.xml,并初始化CordovaPreferences和pluginEntry
CordovaPlugin.java
插件核心类所有自定一的插件均需要继承自该类
PluginManager.java
顾名思义就是管理Cordova项目当中的所有插件,可以找到用来保存插件的如下变量
private final LinkedHashMap<String, CordovaPlugin> pluginMap = new LinkedHashMap<String, CordovaPlugin>();
private final LinkedHashMap<String, PluginEntry> entryMap = new LinkedHashMap<String, PluginEntry>();
以及执行对应插件的方发
/*
通过对应的service名来加载插件实例,并通过action名来执行插件实例的对应方法
比如相机例子,最终调用相机插件通过该类的exec方法 首先根据前端传入的服务名'Camera'来获得对应插件实例
在根据前端传入的action 'takePicture' 来执行实例的takePicture方法
*/
public void exec(final String service, final String action, final String callbackId, final String rawArgs) {
//根据插件的service名来获取对应的插件实例
CordovaPlugin plugin = getPlugin(service);
//如果插件没找到,则直接返回数据给前端,sendPluginResult方法实质是调用 nativeToJsMessageQueue.addPluginResult(cr, callbackId);
//来向js发送数据
if (plugin == null) {
LOG.d(TAG, "exec() call to unknown plugin: " + service);
PluginResult cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
app.sendPluginResult(cr, callbackId);
return;
}
//前端每次执行exec动作原生总会用CallbackContext对象来保存当前动作的callbackId,根据该ID来找对应的成功,失败回调方法并执行
CallbackContext callbackContext = new CallbackContext(callbackId, app);
try {
long pluginStartTime = System.currentTimeMillis();
//执行对应插件的execute方法
boolean wasValidAction = plugin.execute(action, rawArgs, callbackContext);
long duration = System.currentTimeMillis() - pluginStartTime;
if (duration > SLOW_EXEC_WARNING_THRESHOLD) {
LOG.w(TAG, "THREAD WARNING: exec() call to " + service + "." + action + " blocked the main thread for " + duration + "ms. Plugin should use CordovaInterface.getThreadPool().");
}
if (!wasValidAction) {
PluginResult cr = new PluginResult(PluginResult.Status.INVALID_ACTION);
//sendPluginResult方法实质是调用 nativeToJsMessageQueue.addPluginResult(cr, callbackId);
callbackContext.sendPluginResult(cr);
}
} catch (JSONException e) {
PluginResult cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
callbackContext.sendPluginResult(cr);
} catch (Exception e) {
LOG.e(TAG, "Uncaught exception from plugin", e);
callbackContext.error(e.getMessage());
}
}
PluginResult.java
顾名思义就用来保存插件的执行结果
插件的加载流程步骤
1.CordovaActivity.java中调用loadConfig方法来初始化PluginEntry
@SuppressWarnings("deprecation")
protected void loadConfig() {
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(this);//解析config.xml文件并读取首选项和插件
preferences = parser.getPreferences();
preferences.setPreferencesBundle(getIntent().getExtras());
launchUrl = parser.getLaunchUrl();
pluginEntries = parser.getPluginEntries();
Config.parser = parser;
}
2.CordovaActivity.java 调用init方法初始化webview(CordovaWebViewImpl.java实例)
protected void init() {
appView = makeWebView();
createViews();
if (!appView.isInitialized()) {
//appView为CordovaWebViewImpl.java的一个实例
appView.init(cordovaInterface, pluginEntries, preferences);
}
....
}
3.appView(CordovaWebViewImpl.java)调用init方法初始化PluginManager(见CordovaWebViewImpl.java init方法)
4.经过以上步骤相机插件实例就已经存在于PluginManager的对象当中,首先先读config.xml获取相机的类名,服务名
并保存到pluginEntries数组中,之后再将pluginEntries丢给CordovaWebViewImpl实例,并在实例当中用pluginEntries
初始化PluginManager,之后执行任何一个插件都通过PluginManager的来搜索对应插件并执行