zoukankan      html  css  js  c++  java
  • Android WebView与JavaScript交互操作(Demo)

    应用场景:

           为了使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;
      
      @Override
      protected 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目录下面的加载html
        webView.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);
      }
      
      /**
       * 退出监听
       */
      @Override
      public 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);
      }
    
      //*******************华丽的分割线***********************
      @Override
      public 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里跳转,不跳到浏览器那边。
       */
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // 使用自己的WebView组件来响应Url加载事件,而不是使用默认浏览器器加载页面
        webView.loadUrl(url);
        // 记得消耗掉这个事件。给不知道的朋友再解释一下,Android中返回True的意思就是到此为止,
        // 事件就会不会冒泡传递了,我们称之为消耗掉
        return true;
      }
      
      @Override
      public 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);
      }
      
      @Override
      public void onPageFinished(WebView view, String url) {
    //        Toast.makeText(context, "WebViewClient.onPageFinished页面加载完成", Toast.LENGTH_SHORT).show(); 
        Log.e("WebActivity", "页面加载完成");
        super.onPageFinished(view, url);
      }
      
      /**
       * 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
       */
      @Override
      public 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请求    [拓展]
       */
      @Override
      public 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事件
      @Override
      public boolean onJsAlert(WebView view, String url, String message,
          JsResult result) {
        return super.onJsAlert(view, url, message, result);
      }
    
      // onReceivedTitle()方法修改网页标题
      @Override
      public void onReceivedTitle(WebView view, String title) {
        ((Activity)context).setTitle("可以用onReceivedTitle()方法修改网页标题");
        super.onReceivedTitle(view, title);
      }
    
      // 处理Confirm事件
      @Override
      public boolean onJsConfirm(WebView view, String url, String message,
          JsResult result) {
        return super.onJsConfirm(view, url, message, result);
      }
    
      // 处理提示事件
      @Override
      public 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;
      }
    
      @Override
      public 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>
  • 相关阅读:
    解析ASP.NET Mvc开发之EF延迟加载 分类: ASP.NET 2014-01-04 01:29 4017人阅读 评论(1) 收藏
    解析ASP.NET Mvc开发之查询数据实例 分类: ASP.NET 2014-01-02 01:27 5788人阅读 评论(3) 收藏
    解析ASP.NET Mvc开发之查询数据实例
    从明源动力到创新工场这一路走来
    从明源动力到创新工场这一路走来 分类: 程序人生 2013-12-29 07:37 2532人阅读 评论(2) 收藏
    解析ASP.NET WebForm和Mvc开发的区别 分类: ASP.NET 2013-12-29 01:59 11738人阅读 评论(5) 收藏
    解析ASP.NET WebForm和Mvc开发的区别
    MySQL--索引
    MySQL--存储过程
    MySQL--自定义函数
  • 原文地址:https://www.cnblogs.com/longhs/p/4746448.html
Copyright © 2011-2022 走看看