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>
  • 相关阅读:
    codevs 2632 非常好友
    codevs 1213 解的个数
    codevs 2751 军训分批
    codevs 1519 过路费
    codevs 1503 愚蠢的宠物
    codevs 2639 约会计划
    codevs 3369 膜拜
    codevs 3135 River Hopscotch
    数论模板
    JXOJ 9.7 NOIP 放松模拟赛 总结
  • 原文地址:https://www.cnblogs.com/longhs/p/4746448.html
Copyright © 2011-2022 走看看