应用场景:

为了使Android移动项目能够在较短的时间内完成开发,同时降低技术人员开发的成本投入,往往会采用Hybrid APP的开发模式。相关Hybrid APP(混合型应用)参看:http://blog.csdn.net/mahoking/article/details/30235243 采用这种模式,为了解决更好的用户体验,可访问本地资源的能力。势必需要了解与掌握Android(java)与JavaScript之间的交互、相互调用操作的方法与技术。

【转载使用,请注明出处:http://blog.csdn.net/mahoking/article/details/32707013】

知识点介绍:

本文重要的知识点补充是WebView对象(android.webkit.WebView)。
在Android手机中内置了一款高性能webkit内核浏览器,在Android SDK中封装为一个叫做WebView组件。
WebKit是Mac OS X v10.3及以上版本所包含的软件框架(对v10.2.7及以上版本也可通过软件更新获取)。 同时,WebKit也是Mac OS X的Safari网页浏览器的基础。WebKit是一个开源项目,主要由KDE的KHTML修改而来并且包含了一些来自苹果公司的一些组件。
传统上,WebKit包含一个网页引擎WebCore和一个脚本引擎JavaScriptCore,它们分别对应的是KDE的KHTML和KJS。不过, 随着JavaScript引擎的独立性越来越强,现在WebKit和WebCore已经基本上混用不分(例如Google Chrome和Maxthon 3采用V8引擎,却仍然宣称自己是WebKit内核)。
【注意事项】
1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误。
2.如果访问的页面中有Javascript,则webview必须设置支持Javascript。webview.getSettings().setJavaScriptEnabled(true);
3.如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 webview的WebViewClient对象。
4.对于第一点, 如果使用Android SDK提供了一个schema,前缀为"file:///android_asset/"。WebView遇到这样的schema,会去加载assets目录下的资源。如"file:///android_asset/demo.html",可不必使用许可"android.permission.INTERNET"。
在使用WebView组件的过程中可能会接触到WebViewClient与WebChromeClient,那么这两个类到底有什么不同呢?
WebViewClient主要帮助WebView处理各种通知、请求事件的,比如:
  • onLoadResource
  • onPageStart
  • onPageFinish
  • onReceiveError 等
WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等比如:
  • onCloseWindow(关闭WebView)
  • onCreateWindow()
  • onJsAlert (WebView上alert无效,需要定制WebChromeClient处理弹出)
  • onJsPrompt
  • onJsConfirm
  • onReceivedTitle等
两者存在很多的差别,在实际使用过程中,如果你只准备让WebView处理一些html的页面内容,只用WebViewClient就可以了,如果需要产生更丰富的处理效果,比如JS对话框、进度条等,就要使用到WebChromeClient。更进一步的介绍将在下面进行。

【转载使用,请注明出处:http://blog.csdn.net/mahoking/article/details/32707013】


使用方式:

第一步: 本文的演示程序的主界面为activity_web.xml,对应的Activtiy为WebActivtiy.java。
【activity_web.xml】
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@android:color/white"    tools:context=".WebActivity" >    <LinearLayout android:layout_height="wrap_content"         android:background="@drawable/bgcolorblue"        android:id="@+id/top_layout"        android:layout_width="match_parent"        android:layout_alignParentTop="true"        android:orientation="horizontal">        <Button android:layout_height="wrap_content"            android:background="@drawable/titlebackground"            android:layout_weight="1"            android:layout_marginLeft="5dp"            android:layout_marginRight="5dp"            android:layout_width="match_parent"            android:id="@+id/javaCallJs_web_button"            android:text="Java调用无参数JS"/>        <Button android:layout_height="wrap_content"            android:background="@drawable/titlebackground"            android:layout_weight="1"            android:layout_marginLeft="5dp"            android:layout_marginRight="5dp"            android:layout_width="match_parent"            android:id="@+id/javaCallJsParam_web_button"            android:text="Java调用含参数JS"/>    </LinearLayout>    <WebView         android:layout_below="@id/top_layout"        android:id="@+id/webView_web"        android:layout_width="match_parent"    android:layout_height="match_parent"/></RelativeLayout>

【WebActivtiy.java】
package cn.mahaochen.webviewtest;import cn.mahaochen.webviewtest.assist.ButtonListener;import cn.mahaochen.webviewtest.assist.MJavascriptInterface;import cn.mahaochen.webviewtest.assist.MWebChromeClient;import cn.mahaochen.webviewtest.assist.MWebViewClient;import android.os.Bundle;import android.app.Activity;import android.graphics.Color;import android.view.KeyEvent;import android.view.Menu;import android.webkit.WebView;import android.widget.Button;/** * @date 2014-6-20 * @author MaHaochen */public class WebActivity extends Activity {private WebView webView;private Button paramButton;private Button noParamButton;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web);initViews();}private void initViews() {webView = (WebView) findViewById(R.id.webView_web);// 设置WebView对JavaScript的支持webView.getSettings().setJavaScriptEnabled(true);// 从assets目录下面的加载htmlwebView.loadUrl("file:///android_asset/web.html");//自定义WebView的背景颜色webView.setBackgroundColor(Color.TRANSPARENT);//先设置背景色为transparent//webView.setBackgroundResource(R.drawable.webbg);//然后设置背景图片webView.setBackgroundResource(R.drawable.bgcolorblue);//webView.loadUrl("http://www.baidu.com");MWebViewClient mWebViewClient = new MWebViewClient(webView,getApplicationContext());webView.setWebViewClient(mWebViewClient);MWebChromeClient mWebChromeClient = new MWebChromeClient(getApplicationContext());webView.setWebChromeClient(mWebChromeClient);//添加JS调用Android(Java)的方法接口MJavascriptInterface mJavascriptInterface = new MJavascriptInterface(getApplicationContext());webView.addJavascriptInterface(mJavascriptInterface, "WebViewFunc");//初始化按钮,并绑定监听事件,事件的作用是调用JS的功能方法noParamButton = (Button) findViewById(R.id.javaCallJs_web_button);paramButton = (Button) findViewById(R.id.javaCallJsParam_web_button);ButtonListener buttonListener = new ButtonListener(webView);noParamButton.setOnClickListener(buttonListener);paramButton.setOnClickListener(buttonListener);}/** * 退出监听 */@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {if (event.getKeyCode() == KeyEvent.KEYCODE_BACK&& event.getAction() == KeyEvent.ACTION_DOWN&& event.getRepeatCount() == 0) {if(webView.canGoBack()){webView.goBack();return false;}else {WebActivity.this.finish();return true;}}return false;//return super.dispatchKeyEvent(event);}//*******************华丽的分割线***********************@Overridepublic boolean onCreateOptionsMenu(Menu menu) {//getMenuInflater().inflate(R.menu.web, menu);return true;}}

第二步: 从第一步可以看到,以上补充了分别继承自WebViewClient、WebChromeClient的MWebViewClient、MWebChromeClient对象和MJavascriptInterface、ButtonListener对象。对应的对象的相关方法与操作的介绍将会在代码中较详细的叙述。
【MWebViewClient.java】
package cn.mahaochen.webviewtest.assist;import android.content.Context;import android.graphics.Bitmap;import android.net.http.SslError;import android.util.Log;import android.webkit.SslErrorHandler;import android.webkit.WebView;import android.webkit.WebViewClient;import android.widget.Toast;/** * @date 2014-6-20 * @author MaHaochen */public class MWebViewClient  extends WebViewClient {private WebView webView;private Context context;public MWebViewClient(WebView webView) {super();this.webView = webView;}public MWebViewClient(WebView webView, Context context) {super();this.webView = webView;this.context = context;}/** * 在点击请求的是链接是才会调用, * 重写此方法返回true表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边。 */@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {// 使用自己的WebView组件来响应Url加载事件,而不是使用默认浏览器器加载页面webView.loadUrl(url);// 记得消耗掉这个事件。给不知道的朋友再解释一下,Android中返回True的意思就是到此为止,// 事件就会不会冒泡传递了,我们称之为消耗掉return true;}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {//Toast.makeText(context, "WebViewClient.onPageStarted页面开始加载", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "页面加载开始");super.onPageStarted(view, url, favicon);}@Overridepublic void onPageFinished(WebView view, String url) {//Toast.makeText(context, "WebViewClient.onPageFinished页面加载完成", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "页面加载完成");super.onPageFinished(view, url);}/** * 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。 */@Overridepublic void onLoadResource(WebView view, String url) {//Toast.makeText(context, "WebViewClient.onLoadResource", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "onLoadResource");super.onLoadResource(view, url);}/** * 重写此方法可以让webview处理https请求    [拓展] */@Overridepublic void onReceivedSslError(WebView view,SslErrorHandler handler, SslError error) {super.onReceivedSslError(view, handler, error);}}

【MWebChromeClient.java】
package cn.mahaochen.webviewtest.assist;import android.app.Activity;import android.content.Context;import android.webkit.JsPromptResult;import android.webkit.JsResult;import android.webkit.WebChromeClient;import android.webkit.WebView;/** * @date 2014-6-20 * @author MaHaochen */public class MWebChromeClient extends WebChromeClient {private Context context;public MWebChromeClient(Context context) {super();this.context = context;}// 处理Alert事件@Overridepublic boolean onJsAlert(WebView view, String url, String message,JsResult result) {return super.onJsAlert(view, url, message, result);}// onReceivedTitle()方法修改网页标题@Overridepublic void onReceivedTitle(WebView view, String title) {((Activity)context).setTitle("可以用onReceivedTitle()方法修改网页标题");super.onReceivedTitle(view, title);}// 处理Confirm事件@Overridepublic boolean onJsConfirm(WebView view, String url, String message,JsResult result) {return super.onJsConfirm(view, url, message, result);}// 处理提示事件@Overridepublic boolean onJsPrompt(WebView view, String url, String message,String defaultValue, JsPromptResult result) {return super.onJsPrompt(view, url, message, defaultValue, result);}}

【MJavascriptInterface.java】
package cn.mahaochen.webviewtest.assist;import android.content.Context;import android.widget.Toast;/** * @date 2014-6-20 * @author MaHaochen */public class MJavascriptInterface {private Context context;public MJavascriptInterface(Context context) {super();this.context = context;}/** * JS调用Android(Java)无参数的方法 */public void jsCallWebView() {Toast.makeText(context, "JS Call Java!",Toast.LENGTH_SHORT).show();}/** * JS调用Android(Java)含参数的方法 * @param param */public void jsCallWebView(String param) {Toast.makeText(context, "JS Call Java!" + param,Toast.LENGTH_SHORT).show();}}

【ButtonListener.java】
package cn.mahaochen.webviewtest.assist;import cn.mahaochen.webviewtest.R;import android.view.View;import android.view.View.OnClickListener;import android.webkit.WebView;/** * @date 2014-6-20 * @author MaHaochen */public class ButtonListener implements OnClickListener{private WebView webView;public ButtonListener(WebView webView) {super();this.webView = webView;}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.javaCallJs_web_button:webView.loadUrl("javascript:javacalljs()"); // 无参数调用break;case R.id.javaCallJsParam_web_button:webView.loadUrl("javascript:javacalljsparam(" + "'含参数'"+ ")"); // 无参数调用break;default:break;}}}

第三步: 以上是全部的Java代码部分的信息,本例旨为演示WebView(Java)与JS(JavaScript)的互操作。所以需要补充另两个资源文件web.html与jump.html页面,该页面位于项目的assets文件夹下。
【web.html】
<html><head><meta http-equiv="Content-Type" content="text/html; charset=GBK"/><script type="text/javascript">//Java调用JS代码无参数function javacalljs(){ document.getElementById("content").innerHTML +=              "<br\>java调用了js函数";  }//Java调用JS代码有参数function javacalljsparam(param){ document.getElementById("content").innerHTML +=              "<br\>java调用了js函数含参数param"+param;  }function testFunc(){window.WebViewFunc.jsCallWebView();}</script><title>测试页面</title></head><body><a onClick="testFunc()">无参数JS调用java代码</a><br/> <a onClick="window.WebViewFunc.jsCallWebView('含有参数')">含参数调用java代码</a><br/> <br /><div id="content">内容显示 <a href="jump.html" target="_self">跳转新页面jump.html</a></div>  </body></html>

【jump.html】
<html><head><meta http-equiv="Content-Type" content="text/html; charset=GBK"/><script type="text/javascript">//Java调用JS代码无参数function javacalljs(){ document.getElementById("content").innerHTML +=              "<br\>java调用了js函数";  }//Java调用JS代码有参数function javacalljsparam(param){ document.getElementById("content").innerHTML +=              "<br\>java调用了js函数含参数param"+param;  }function testFunc(){window.WebViewFunc.jsCallWebView();}</script><title>测试页面</title></head><body><a onClick="testFunc()">无参数JS调用java代码</a><br/> <a onClick="window.WebViewFunc.jsCallWebView('含有参数')">含参数调用java代码</a><br/> <br /><div id="content">内容显示</div>  </body></html>

■注:由于本演示案例添加必要的图片文件与样式文件,才可以出现以下效果截图,所以如果获取完整的效果,请在【下载地址】栏,自行下载完整项目。
【转载使用,请注明出处:http://blog.csdn.net/mahoking/article/details/32707013】

效果截图:


下载地址:

http://download.csdn.net/detail/ma_hoking/7525549 点击下载

参考文献:

1、 http://www.cnblogs.com/oakpip/archive/2011/04/08/2009800.html
2、 http://blog.csdn.net/jackyhuangch/article/details/8310033

更多相关文章

  1. mybatisplus的坑 insert标签insert into select无参数问题的解决
  2. Python技巧匿名函数、回调函数和高阶函数
  3. python list.sort()根据多个关键字排序的方法实现
  4. Android(安卓)Wifi模块分析(三)
  5. Android中dispatchDraw分析
  6. Android四大基本组件介绍与生命周期
  7. android中文api(89)——ViewManager
  8. Android(安卓)Service AIDL
  9. Android调用天气预报的WebService简单例子

随机推荐

  1. Android界面开发简介
  2. 在 Android(安卓)字符串资源中直接使用 E
  3. Android中Shape和Selector的结合使用。
  4. Android(安卓)build.gradle配置buildConf
  5. 开发具备语音识别功能的 Android* 应用
  6. Android介绍
  7. Android XML解析学习——Sax方式(续)
  8. Android(安卓)studio断点调试(全在这里)
  9. Android Animation学习笔记
  10. Android在Eclipse环境下安装配置