Android WebView详解(二):Android原生与JS互调


声明:本文转载自https://my.oschina.net/u/1433837/blog/1619343,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

Android 去调用JS 的代码

  • 通过WebView的loadUrl()

    先写一个html,很简单的一个代码,alert显示。

    android_load_js.html

      <!DOCTYPE html>   <html>      <head>         <meta charset="utf-8">         <title>Android调用 JS 代码demo</title>   // JS代码        <script>          // Android需要调用的方法          function callJS(){             alert("Android调用了JS的callJS方法");          }       </script>      </head>   </html> 

    在Activity中

      mWebSettings = mWebview.getSettings();   //与JS交互开关   mWebSettings.setJavaScriptEnabled(true);   //设置允许JS弹窗	       mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);   mWebview.loadUrl("file:///android_asset/android_load_js.html");    //在这我用了一个TextView 点击事件中去调用JS中的方法   beginLoading.setOnClickListener(new View.OnClickListener() {       [@Override](https://my.oschina.net/u/1162528)       public void onClick(View view) {           //执行JS方法     		mWebview.loadUrl("javascript:callJS()");       }   });     mWebview.setWebChromeClient(new WebChromeClient() {       //获取网站标题       [@Override](https://my.oschina.net/u/1162528)       public void onReceivedTitle(WebView view, String title) {           System.out.println("标题在这里");           mtitle.setText(title);       }        //获取加载进度       [@Override](https://my.oschina.net/u/1162528)       public void onProgressChanged(WebView view, int newProgress) {           if (newProgress < 100) {               String progress = newProgress + "%";               loading.setText(progress);           } else if (newProgress == 100) {               String progress = newProgress + "%";               loading.setText(progress);           }       }    	//由于设置了弹窗检验调用结果,所以需要支持js对话框       //webview只是载体,内容的渲染需要使用webviewChromClient类去实现       //通过设置WebChromeClient对象处理JavaScript的对话框       //设置响应js 的Alert()函数       [@Override](https://my.oschina.net/u/1162528)       public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {           AlertDialog.Builder b = new AlertDialog.Builder(TestActivity.this);           b.setTitle("Alert");           b.setMessage(message);           b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {               [@Override](https://my.oschina.net/u/1162528)               public void onClick(DialogInterface dialog, int which) {                   result.confirm();               }           });           b.setCancelable(false);           b.create().show();           return true;       }   }); 
  • 通过WebView的evaluateJavascript()

    该方法比第一种方法效率更高,因为该方法的执行不会使页面刷新,而第一种方法(loadUrl)的执行则会。该方法在Android 4.4 后才可使用,该方法在主线程执行

      //将上面webView.loadUrl("javascript:callJS()")替换为   mWebview.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {       @Override       public void onReceiveValue(String value) {           //此处为 js 返回的结果       }   });	 

    可以做一下兼容:

       if (Build.VERSION.SDK_INT > 18) {       mWebview.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {           @Override           public void onReceiveValue(String value) {               //此处为 js 返回的结果           }       });   } else {       mWebview.loadUrl("javascript:callJS()");   } 

JS 去调用 Android的代码

  • 通过WebView的addJavaScriptInterface()进行对象映射

    html

      <!DOCTYPE html>   <html>      <head>         <meta charset="utf-8">         <title>DEMO</title>         <script>            function callAndroid(){           // 由于对象映射,所以调用test对象等于调用Android映射的对象               test.showLog("js调用了android中的hello方法");            }         </script>      </head>      <body>         //点击按钮则调用callAndroid函数         <button type="button" id="button1" onclick="callAndroid()" text="Android"></button>      </body>   </html> 

    映射的代码

      package org.professor.procartoon.temp;    import android.webkit.JavascriptInterface;    import org.professor.procartoon.utils.LogUtils;    /**    * Created by Caipeng on 2018.02.06.    */   public class JSObject {    	/**   	 * 定义JS需要调用的方法被JS调用的方法必须加入@JavascriptInterface注解   	*/       @JavascriptInterface       public void showLog(String text) {           LogUtils.i(text);       }   } 

    在Activity中的测试代码

      mWebSettings.setJavaScriptEnabled(true);   mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);   //通过addJavascriptInterface()将Java对象映射到JS对象   //参数1:Javascript对象名   //参数2:Java对象名   mWebview.addJavascriptInterface(new JSObject(),"test");   mWebview.loadUrl("file:///android_asset/android_load_js.html"); 
  • 通过WebViewClient的ShouldOverrideUrlLoading() 方法进行回调拦截

    Android通过 WebViewClient 的回调方法shouldOverrideUrlLoading ()拦截 url,解析该 url 的协议,如果检测到是预先约定好的协议,就调用Android相应的方法。

    html Document

      <!DOCTYPE html>   <html>      <head>         <meta charset="utf-8">         <title>DEMO</title>         <script>            function callAndroid(){   			//协议org://professor?arg1=com&arg2=test               document.location = "org://professor?arg1=111&arg2=222";            }         </script>      </head>      <body>         //点击按钮则调用callAndroid函数          <button type="button" id="button1" onclick="callAndroid()">CallAndroid</button>      </body>   </html> 

    JAVA代码

      @Override   public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {       //一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)       Uri uri = Uri.parse(request.getUrl().toString());       if (uri.getScheme().equals("org")) {           if (uri.getAuthority().equals("professor")) {               LogUtils.i(uri.getQueryParameter("arg1"));           }           return true;       }        return super.shouldOverrideUrlLoading(view, request);   } 

    备注

    JS获取Android方法的返回值复杂。 如果JS想要得到Android方法的返回值,只能通过 WebView 的loadUrl ()去执行 JS 方法把返回值传递回去,相关的代码如下:

      //Android原生调用js   mWebView.loadUrl("javascript:returnResult(" + result + ")");    //需要在html中接收   function returnResult(result){       alert("result is" + result);   } 
  • 通过WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息

    首先介绍下JS中的alert()、confirm()、prompt()三个方法

    • alert(),弹出警告窗,没有返回值,在文本加入\n可换行
    • confirm(),弹出确认框,两个返回值,返回布尔值,通过该值可以判断点击是确认还是取消(true表示点击了确认,false表示点击了取消)
    • prompt(),弹出输入框,任意设置返回值,点击确认返回输入框中的值,点击取消返回null

    原理:Android通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调分别拦截JS对话框 (即上面的三个方法),得到他们的消息内容,然后解析即可。

    常用的拦截是:拦截 JS的输入框(即prompt()方法)。因为只有prompt()可以返回任意类型的值,操作最全面方便、更加灵活;而alert()对话框没有返回值confirm()对话框只能返回两种状态(确定 / 取消)两个值

    html代码

      <!DOCTYPE html>   <html>      <head>         <meta charset="utf-8">         <title>DEMO</title>         <script>            function callAndroid(){               //document.location = "org://professor?arg1=111&arg2=222";               var result=prompt("org://professor?arg1=111&arg2=222");               alert("demo " + result);            }         </script>      </head>      <body>         //点击按钮则调用callAndroid函数          <button type="button" id="button1" onclick="callAndroid()">CallAndroid</button>      </body>   </html> 

    JAVA代码

      @Override   public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {        //一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)       Uri uri = Uri.parse(url);       if (uri.getScheme().equals("org")) {           if (uri.getAuthority().equals("professor")) {               LogUtils.i(uri.getQueryParameter("arg1"));               //参数result:代表消息框的返回值(输入值)               result.confirm("js调用了Android的方法成功啦");           }           return true;       }        return super.onJsPrompt(view, url, message, defaultValue, result);   } 
  • 结语

    由上可以比较,根据第三种方式,即:通过WebChromeClient的方法拦截比较灵活一些

本文发表于2018年02月07日 00:31
(c)注:本文转载自https://my.oschina.net/u/1433837/blog/1619343,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2093 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

万稳万当,不如一默。任何一句话,你不说出来便是那句话的主人,你说了出来,便是那句话的奴隶。

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1