文档章节

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

蔡小鹏
 蔡小鹏
发布于 2018/02/06 22:49
字数 1369
阅读 572
收藏 0

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的方法拦截比较灵活一些

© 著作权归作者所有

蔡小鹏
粉丝 37
博文 42
码字总数 72958
作品 0
海淀
Android工程师
私信 提问
WebView深度学习(一)之WebView的基本使用以及Android和js的交互

前言:随着市场需求的不断变化,原生安卓已经无法满足客户的需要了,现在很多app都在使用Android和h5的交互实现某些功能,比如商品详情页,文章详情页面,商品点评页面,还有某些复杂的展示页...

aweiloveandroid
2017/07/01
0
0
Android H5混合开发那点事(一)H5调用原生Android实现扫一扫功能

开发软件:AndroidStudio,WebStorm 扫一扫库文件下载:compile 'com.github.yuzhiqiang1993:zxing:2.2.5' 关键点:安卓与H5 方法互调,数据互通 整体思路:通过H5调用安卓原生方法进行扫一扫...

极客简讯
02/19
0
0
Android WebView基本使用

WebView介绍 Android WebView在Android平台上是一个特殊的View, 基于webkit引擎、展现web页面的控件,这个类可以被用来在你的app中仅仅显示一张在线的网页,还可以用来开发浏览器。WebView...

临江仙卜算子
2018/07/06
44
0
使用Kotlin:让Android与JS交互的详解

先来说说什么是JS交互: 说的俗一点就是通过我们项目中的控件来调用HTML里的JS代码,也可以通过JS来调用项目中的代码。 Android与JS之间的桥梁就是WebView了,我们是通过WebView来实现他们的...

富江___
2018/06/11
0
0
android WebView详解

浏览器控件是每个开发环境都具备的,这为马甲神功提供了用武之地,windows的有webbrowser,android和ios都有webview。只是其引擎不同,相对于微软的webbrowser,android及ios的webview的引擎...

amigos_wu
2012/06/25
9.4K
1

没有更多内容

加载失败,请刷新页面

加载更多

mysql-connector-java升级到8.0后保存时间到数据库出现了时差

在一个新项目中用到了新版的mysql jdbc 驱动 <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.18</version> ......

ValSong
今天
5
0
Spring Boot 如何部署到 Linux 中的服务

打包完成后的 Spring Boot 程序如何部署到 Linux 上的服务? 你可以参考官方的有关部署 Spring Boot 为 Linux 服务的文档。 文档链接如下: https://docs.ossez.com/spring-boot-docs/docs/r...

honeymoose
今天
6
0
Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

1. 前言 生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以...

码农小胖哥
今天
9
0
ZetCode 教程翻译计划正式启动 | ApacheCN

原文:ZetCode 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN 学习资源 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 ...

ApacheCN_飞龙
今天
5
0
CSS定位

CSS定位 relative相对定位 absolute绝对定位 fixed和sticky及zIndex relative相对定位 position特性:css position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left属性则...

studywin
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部