Cordova 3.x 基础(11) -- JS是如何调用本地API的?

Cordova应用基于Webview,所以后台代码和js交互都是基于Webview(Webkit)的接口的。

Android:WebView(WebKit-based) WebView(4.4 Chromium-based) Updatable-WebViews(5+)
@JavascriptInterface/WebView#addJavascriptInterface()
参考源码 [url=https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/ExposedJsApi.java]ExposedJsApi.java[/url]

iOS:UIWebView(iOS 4+) WKWebView(iOS 8.1+)
UIWebViewDelegate/UIWebView#stringByEvaluatingJavaScriptFromString()
参考源码 [url=https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/CDVWebViewDelegate.m]CDVWebViewDelegate.m[/url]
[img]http://dl2.iteye.com/upload/attachment/0094/4262/5c996053-31bf-3915-90cd-c32be5645fd3.png[/img]

以下以Android调用照相机为例,简单说明一下调用及回调过程。

[b](1)创建的过程[/b]

①添加插件
[quote]cordova plugin add org.apache.cordova.camera[/quote]
在plugins的目录下创建org.apache.cordova.camera文件夹,并将该Plugin的所有代码Copy进去,具体代码依赖关系都记录在plugin.xml里。

②创建Android工程
[quote]cordova platform add android[/quote]
从上边的Plugin文件夹中把Java文件和js文件Copy到Android工程的相应的文件夹下。
[list][*]platforms\android\src\org\apache\cordova\camera\CameraLauncher.java等
[*]platforms\android\assets\www\plugins\org.apache.cordova.camera\www\Camera.js等[/list]

其中CameraLauncher扩展自CordovaPlugin,而CordovaPlugin定义在platforms\android\CordovaLib中,它是Cordova的基础框架代码。

[b](2)调用的过程(JS->Native)[/b]

①HTML中引入cordova.js
[quote]<script type="text/javascript" src="cordova.js"></script>[/quote]
先做初始化处理,后根据cordova_plugins.js加载所有plugin的js文件。

②在deviceready事件中调用Camera
navigator.camera.getPicture(onSuccess, onFail,   
{ quality: 50,
allowEdit: true,
destinationType: destinationType.DATA_URL });


③调用Camera.js的getPicture方法
assets\www\plugins\org.apache.cordova.camera\www\Camera.js

getPicture()
->
exec(successCallback, errorCallback, "Camera", "takePicture", args)
->
function androidExec(success, fail, service, action, args) ***cordova.js
->
var messages = nativeApiProvider.get().exec(service, action, callbackId, argsJson);

④调入Java的exec()方法
在CordovaWebView初期化的时候会根据Android的版本,将ExposedJsApi对象添加到CordovaWebView中。
this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
所以nativeApiProvider.get()的时候会根据 _cordovaNative 对象是否存在来判断是使用JavascriptInterface方式,还是使用prompt方式。

如果使用JavascriptInterface方式(Android 4.2以上版本),直接进入ExposedJsApi.java中定义了@JavascriptInterface标示的exec()方法 。

如果使用prompt方式,CordovaChromeClient.java中重写了onJsPrompt()方法,来调用exposedJsApi.exec()。
prompt(argsJson, 'gap:'+JSON.stringify([service, action, callbackId]));

总之入口都是exposedJsApi.exec().

@JavascriptInterface
public String exec(String service, String action, String callbackId, String arguments)
->
pluginManager.exec(service, action, callbackId, arguments);
PluginManager根据service调用获取到相应的CordovaPlugin
->
CameraLauncher.execute(String action, JSONArray args, CallbackContext callbackContext)
CameraLauncher根据action,这里是“takePicture”做本地API调用。
->
takePicture()
->
new Intent("android.media.action.IMAGE_CAPTURE");
cordova.startActivityForResult()
调用CordovaInterface(CordovaActivity->Activity)的startActivityForResult

[b](3)回调的过程(Native->JS)[/b]

①上述API调用成功后,在onActivityResult(CameraLauncher.java)设置结果
onActivityResult(int requestCode, int resultCode, Intent intent)

// Send Uri back to JavaScript for viewing image
this.callbackContext.success(uri.toString());

②退回到ExposedJsApi的exec()方法
jsMessageQueue.setPaused(false);
->
NativeToJsMessageQueue的onNativeToJsMessageAvailable()
->
sendMessageMethod = webViewCore.getClass().getDeclaredMethod("sendMessage", Message.class)
->
sendMessageMethod.invoke(webViewCore, execJsMessage)

③cordova.js中接收消息
androidExec.processMessages(messages)
->
processMessage(message)
->
cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback);
调用定义好的成功或者失败的JS回调函数。(payload为回传值)

以上就是完整的过程。

参考:
[url=http://blog.devtang.com/blog/2012/03/24/talk-about-uiwebview-and-phonegap/]http://blog.devtang.com/blog/2012/03/24/talk-about-uiwebview-and-phonegap/[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值