目录前言技术选型技术原理1. 如何本地加载url对应的资源2. WEBview如何使用js调用app原生api3. app原生api如何回调webview中的js4. 多个plugi
从原理到应用复盘一下自己做过的所有项目,希望能让我自己过两年仍然能看懂现在写的代码哈哈。在项目里我只负责了Android的开发包括插件开发和集成,iOS没摸到,有机会也得自己玩下,但是这篇文章不会接触。
现在Hybrid混合开发框架很多,Apche Cordova/React Native/Flutter等等等等。然而公司需求是2018年6月提的,Flutter 1.0在半年之后才出生,所以当时团队TL比较了RN与Cordova后基于以下几点选择了Cordova。
我们的应用跑在一台定制的Android终端,性能不是很好,在最后某些js动画场景里,以及一些js-native的调用里卡的不行,最后优化了下,效果也算还不错。这里建议如果对性能要求很高的项目,一定慎重考虑Cordova这种webview方案
项目最后选择了React + Mirrorx + Cordova的方案(当时有Dva, 但是由于Dva没有英文文档,而我们的项目是需要美国分团队共同维护的,所以选择了Mirrorx)
架构图
本质上其实就是往app里面塞一个webview,通过file协议, 本地加载index.html
那么这里会有三个问题
我们项目中通过eject暴露Webapck配置, 配置打包路径直接打进www文件夹。 通过Android的webview.loadUrl方法通过file协议load本地index.html。在Google inject中也可以看到对应的url. 对应的cordova代码如下
public class CordovaViewTestActivity extends Activity implements Cordovainterface {
CordovaWebView cwv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
cwv = (CordovaWebView) findViewById(R.id.tutorialView);
cwv.loadUrl("file:///android_asset/www/index.html");
}
2.1 通过addjavascriptInterface 及 @JavascriptInterface实现
2.2 通过WebClientChrome中的三个方法onJsAlert, onJsConfirm, onJsPrompt实现
当chromium webkit内核的webview调用window.alert, window.confirm, window.prompt方法时,对应的WebClientChrome的那三个方法同样会被执行
在cordova中会首先判断有没有设置navtiveApi
var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
在Android部分
var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJSON);
// If argsJson was received by Java as null, try again with the PROMPT bridge mode.
// This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
androidExec(success, fail, service, action, args);
androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
} else if (msgs) {
messagesFromNative.push(msgs);
// Always process async to avoid exceptions messing up stack.
nextTick(proceSSMessages);
}
如果有nativeApi即设备支持@JavascriptInterface注解, 则走addJavascriptInterface,否则走onJsPrompt
js端生成callback function id,传给native, native需要回调js时,回调对应的callbackId给js
private String callbackId; // 在js端生成,保存在native端
private CordovaWebView webView;
protected boolean finished; //这个callback是否结束,如果结束在js端(cordova.js)就会把这个callbackid从列表中删掉,否则这个callback将一直存在,也就是说明你可以用这个callbackContext一直和js保持通信
回调方式:
public static class LoadUrlBridgeMode extends BridgeMode {
public static class EvalBridgeMode extends BridgeMode {
public static class OnlineEventsBridgeMode extends BridgeMode
多个plugin的情况下,cordova是如何通过cordova.exec(...’pluginName’...)定位到相应的plugin的
当Cordova框架启动时候,CordovaActivity类中的onCreate方法调用loadUrl方法。在第一次loadUrl方法时,就会去初始化PluginManager并加载plugin,PluginManager加载plugin,将plugin的Class名字保存到一个HashMap中,用service名字作为key值。当JS端通过JavascriptInterface接口的SystemExposedJsApi对象请求Android时,PluginManager会从hashmap中查找到plugin,如果该plugin还未实例化,利用java反射机制实例化该plugin,并执行plugin的execute方法。
cordova build的时候会默认使用项目www目录作为资源目录,打包进assets中。 项目工期紧,直接用了cra创建的项目,我们使用eject,再修改打包路径(实际当时有其他插件可以暴露打包路径配置)。
// webpack.config.prod.js
module.exports = {
...
output: {
...
// The build folder.
path: resolveApp('www'),
}
}
场景: 我们项目集成其他项目组的自研plugin的功能后,用户输入device ID和divice Name后,点击connect按钮,就可以通过mobile连接上其他项目组的硬件设备
前端调用test.connect(deviceID, deviceName, callback), 其中callback的逻辑是接收并判断java端传回的message。在连接上device后, java使用contextCallback.success(”success”)来进行回调 ,callback接收到message为success, 就更改mobile端我们前端的相应状态为连接成功
第一次连接之后,即java调用了contextCallback.success(“success”), 然后js中调用了callback(‘success’) ,项目页面显示已连接, 断开后,第二次再次调用contextCallback.success(“success”)无法正常连接,无法正常调用js这边的callback
原因:
finished一开始没有初始化,走下面的else,被赋值为true, 然后调用webView.sendResult,第二次调用就直接return了。
解决方案:keepCallback (当时官方文档没有提到callback只能调一次的问题,翻源码才看到)
以上就是Apache Cordova Android原理应用实例详解的详细内容,更多关于Apache Cordova Android的资料请关注编程网其它相关文章!
--结束END--
本文标题: Apache Cordova Android原理应用实例详解
本文链接: https://lsjlt.com/news/171021.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0