标签:
本文的目的是学习如何进行Android native+html5的混合开发。
首先什么是Android native+html5的混合开发?
通常来说就是使用html5+css+JavaScript等Web前端开发技术开发出html文件,再通过Android 的WebView加载html文件实现App的UI开发 ,Android系统提供数据库、通讯录、摄像头、音频等API供JavaScript调用。
因此在混合开发过程中需要解决下面三个问题:
1.Android 如何调用JavaScript方法
2.JavaScript如何调用Android方法
3.JavaScrpit如何调用Android异步方法
这三个问题解决之后,Android native+html5的混合开发就只需要分别进行html5+css+JavaScript 的Web前端开发和Android native开发了。
下面通过示例来学习如何解决上面三个问题。
1.1 设置WebView的WebSettings使WebView 可以执行JavaScript。
webview = (WebView) findViewById(R.id.myWebView);
// 得到设置属性的对象
WebSettings webSettings = webview.getSettings();
// 使能JavaScript
webSettings.setJavaScriptEnabled(true);
// 支持中文,否则页面中中文显示乱码
webSettings.setDefaultTextEncodingName("UTF-8");
1.2 为WebView添加JavascriptInterface,这一步至关重要,为JavaScript调用Android代码提供了接口
//传入一个Java对象和一个接口名,在JavaScript代码中用这个接口名代替这个对象,通过接口名调用Android接口的方法
webview.addJavascriptInterface(new JavascriptInterfaceImpl(this,
webview), "Android");
JavascriptInterfaceImpl 的实现见Demo。
在 JavascriptInterfaceImpl 中定义了
1.void showToast(String toast)//显示Toast
2.String syncExec()//同步执行方法
3.void asyncExec(final String msg, final String callbackId)//异步执行方法
三个方法,下面会通过这三个方法,来学习JavaScript对Android方法的调用。
1.3 为WebView设置WebViewClient,这一步对使用JavaScript不是必须的。
// WebViewClient 主要帮助WebView处理各种通知、请求事件的
webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
1.4 为WebView设置WebChromeClient,不设置WebChromeClient的话,JavaScript的弹框消息会无法显示。
1 // WebChromeClient主要用来辅助WebView处理Javascript的对话框、网站图标、网站标题以及网页加载进度等
2 webview.setWebChromeClient(new WebChromeClient() {
3 @Override
4 public void onReceivedTitle(WebView view, String title) {
5 }
6
7 @Override
8 public boolean onJsAlert(WebView view, String url, String message,
9 JsResult result) {
10 return super.onJsAlert(view, url, message, result);
11 }
12 });
1.5 加载本地html页面
// 载入页面:本地html资源文件
webview.loadUrl("file:///android_asset/sample.html");
Sample.html文件放置在assets目录下面,Sample.html的具体实现查看Demo
Android调用JavaScript方法非常简单,例如 Sample.html中定义了一个名为myFunction的方法
1 function myFunction() 2 { 3 alert("Hello World!"); 4 } 5
在Android里面执行下面代码即可调用该JavaScript方法
1 webview.loadUrl("javascript:myFunction()");
注意两点:
1.webview.loadUrl()方法需要在UI线程中调用
2.调用的JavaScript方法需要定义在WebView加载的html文件中
在Android4.4以上的系统还提供了另外一个方法可以执行JavaScrpit代码
public void evaluateJavascript (String script, ValueCallback<String> resultCallback)
在1.2中我们给WebView添加JavascriptInterface,JavascriptInterface的实现类是JavascriptInterfaceImpl,接口名是"Android",因此我们可以在JavaScript代码中通过Android这个接口名来调用JavascriptInterfaceImpl里面的Android方法。
例如,调用JavascriptInterfaceImpl的syncExec方法.该方法的结果是同步返回的
1 //调用绑定的Java对象的方法,同步显示android返回的内容
2 function showAndroidSyncMsg()
3 {
4 console.log("showAndroiHello method");
5 var str = Android.syncExec();
6 alert(str);
7 }
JavaScript如何调用Android异步方法是一个难点,因为没有提供直接的接口可以调用Android异步方法,并且接收Android异步返回的结果.在此之前我们先看下Java是如何处理异步方法的
1 public interface Callback { 2 void onResult(String result); 3 } 4 5 public void asyncFun(final Callback callback) { 6 new Thread() { 7 @Override 8 public void run() { 9 SystemClock.sleep(3 * 1000); 10 callback.onResult("async result"); 11 } 12 }.start(); 13 } 14 15 public void test() { 16 this.asyncFun(new Callback() { 17 18 @Override 19 public void onResult(String result) { 20 Log.d(TAG, "result == " + result); 21 } 22 }); 23 }
在Java中是通过定义一个回调接口,在异步方法执行完后,在回调这个回调接口的方法,将结果传给调用者.
同样的道理,我们也可以为JavaScript调用Android异步方法设计相同的调用模式.
例如
1 /**
2 * 异步方法
3 * @param msg
4 * @param callbackId
5 */
6 @JavascriptInterface
7 public void asyncExec(final String msg, final String callbackId) {
8 new Thread() {
9 @Override
10 public void run() {
11 SystemClock.sleep(5 * 1000);
12 mHandler.post(new Runnable() {
13 @Override
14 public void run() {
15 String url = "javascript:" + callbackId + "(‘" + msg
16 + " from android " + "‘)";
17 mWebView.loadUrl(url);
18 }
19 });
20 }
21 }.start();
22 }
该方法有两个参数,一个是传进来的数据,一个是要回调的JavaScript方法名.asyncExec在异步执行完后,通过webview.loadUrl()方法将结果回调给JavaScript的回调方法.
在JavaScript端需要定义一个回调方法接收回调结果,例如:
//调用绑定的Java对象的方法,异步显示android返回的内容 function showAndroidAsyncMsg() { console.log("showAndroidAsyncMsg method"); //异步回调方法 //调用android 异步接口 Android.asyncExec("异步消息", "onCallback"); } // 定义回调方法 function onCallback(msg) { alert(msg); }
至此,已经学习了Android和JavaScript之间的相互调用,Android版本的Html5开发框架PhoneGap在实现Android和JavaScript的相互调用的时候和本文使用的相同的方式,包括异步调用的设计.但是PhoneGap的核心Cordova对参数类型的转换,异步消息的队列管理做了很好的封装,让使用者可以更简单的实现Android和JavaScript之间的混合开发.下一篇文章会介绍Cordova框架.
思考:
1.Android和JavaScript之间能传哪些类型的参数?如果将各种类型的Android参数传递给JavaScript,JavaScript如何解析?
标签:
原文地址:http://www.cnblogs.com/kuangbiao/p/5246492.html