Android WebView与JS交互全面详解(小结)

Android 和 H5 都是移动开发应用的非常广泛。市面上很多App都是使用Android开发的,但使用Android来开发一些比较复杂附属类,提示性的页面是得不偿失的。而H5具有开发速度快,更新不用依赖于App的更新,只需要服务端更新相应的页面即可,所以,App和H5页面相结合就显得尤为重要。而android和H5都不可能每次都是独立存在的,而是相互影响也相互的调用,获取信息等,例如,H5页面要获取App中的用户的基本信息,或者App端要操作H5页面等,下面来看看这两是怎么交互的

目录

1. 交互方式总结

Android与JS通过WebView互相调用方法,实际上是:

  1. Android去调用JS的代码
  2. JS去调用Android的代码

二者沟通的桥梁是WebView

对于Android调用JS代码的方法有2种:

  1. 通过WebView的loadUrl()
  2. 通过WebView的evaluateJavascript()

对于JS调用Android代码的方法有3种:

  1. 通过WebView的addJavascriptInterface()进行对象映射
  2. 通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url
  3. 通过 WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt()消息

2. 具体分析

2.1 Android通过WebView调用 JS 代码

方式1:通过WebView的loadUrl()

实例介绍:点击Android按钮,即调用WebView JS(文本名为javascript)中callJS()

具体使用:

步骤1:将需要调用的JS代码以.html格式放到src/main/assets文件夹里

为了方便展示,本文是采用Andorid调用本地JS代码说明;

实际情况时,Android更多的是调用远程JS代码,即将加载的JS代码路径改成url即可

需要加载JS代码:javascript.html

// 文本名:javascript
<!DOCTYPE html>
<html>

  <head>
   <meta charset="utf-8">
   <title>Carson_Ho</title>

// JS代码
   <script>
// Android需要调用的方法
  function callJS(){
   alert("Android调用了JS的callJS方法");
  }
</script>

  </head>

</html>

步骤2:在Android里通过WebView设置调用JS代码

public class MainActivity extends AppCompatActivity {

  WebView mWebView;
  Button button;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mWebView =(WebView) findViewById(R.id.webview);

    WebSettings webSettings = mWebView.getSettings();

    // 设置与Js交互的权限
    webSettings.setJavaScriptEnabled(true);
    // 设置允许JS弹窗
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

    // 先载入JS代码
    // 格式规定为:file:///android_asset/文件名.html
    mWebView.loadUrl("file:///android_asset/javascript.html");

    button = (Button) findViewById(R.id.button);

    button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        // 必须另开线程进行JS方法调用(否则无法调用)
        mWebView.post(new Runnable() {
          @Override
          public void run() {

            // 注意调用的JS方法名要对应上
            // 调用javascript的callJS()方法
            mWebView.loadUrl("javascript:callJS()");
          }
        });

      }
    });

    // 由于设置了弹窗检验调用结果,所以需要支持js对话框
    // webview只是载体,内容的渲染需要使用webviewChromClient类去实现
    // 通过设置WebChromeClient对象处理JavaScript的对话框
    //设置响应js 的Alert()函数
    mWebView.setWebChromeClient(new WebChromeClient() {
      @Override
      public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
        AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this);
        b.setTitle("Alert");
        b.setMessage(message);
        b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            result.confirm();
          }
        });
        b.setCancelable(false);
        b.create().show();
        return true;
      }

    });

  }
}

效果图

特别注意:JS代码调用一定要在 onPageFinished() 回调之后才能调用,否则不会调用。

onPageFinished()属于WebViewClient类的方法,主要在页面加载结束时调用

方式2:通过WebView的evaluateJavascript()

优点:

  1. 该方法比第一种方法效率更高、使用更简洁。
  2. 因为该方法的执行不会使页面刷新,而第一种方法(loadUrl )的执行则会。

Android 4.4 后才可使用

具体使用

// 只需要将第一种方法的loadUrl()换成下面该方法即可
  mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
      //此处为 js 返回的结果
    }
  });
}

2.1.2 方法对比

方式对比图

2.1.3 使用建议

两种方法混合使用,即Android 4.4以下使用方法1,Android 4.4以上方法2

// Android版本变量
final int version = Build.VERSION.SDK_INT;
// 因为该方法在 Android 4.4 版本才可使用,所以使用时需进行版本判断
if (version < 18) {
  mWebView.loadUrl("javascript:callJS()");
} else {
  mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
      //此处为 js 返回的结果
    }
  });
}

2.2 JS通过WebView调用 Android 代码

2.2.1 方法分析

方式1:通过 WebView的addJavascriptInterface()进行对象映射

步骤1:定义一个与JS对象映射关系的Android类:AndroidtoJs

AndroidtoJs.java(注释已经非常清楚)

// 继承自Object类
public class AndroidtoJs extends Object {

  // 定义JS需要调用的方法
  // 被JS调用的方法必须加入@JavascriptInterface注解
  @JavascriptInterface
  public void hello(String msg) {
    System.out.println("JS调用了Android的hello方法");
  }
}

步骤2:将需要调用的JS代码以.html格式放到src/main/assets文件夹里

需要加载JS代码:javascript.html

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8">
   <title>Carson</title>
   <script>

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

步骤3:在Android里通过WebView设置Android类与JS代码的映射

public class MainActivity extends AppCompatActivity {

  WebView mWebView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mWebView = (WebView) findViewById(R.id.webview);
    WebSettings webSettings = mWebView.getSettings();

    // 设置与Js交互的权限
    webSettings.setJavaScriptEnabled(true);

    // 通过addJavascriptInterface()将Java对象映射到JS对象
    //参数1:Javascript对象名
    //参数2:Java对象名
    mWebView.addJavascriptInterface(new AndroidtoJs(), "test");//AndroidtoJS类对象映射到js的test对象

    // 加载JS代码
    // 格式规定为:file:///android_asset/文件名.html
    mWebView.loadUrl("file:///android_asset/javascript.html");

特点

优点:使用简单,仅将Android对象和JS对象映射即可

缺点:存在严重的漏洞问题

方式2:通过 WebViewClient 的方法shouldOverrideUrlLoading ()回调拦截 url

**具体原理: **

Android通过 WebViewClient 的回调方法shouldOverrideUrlLoading ()拦截 url解析该 url 的协议

如果检测到是预先约定好的协议,就调用相应方法

即JS需要调用Android的方法

具体使用:

步骤1:在JS约定所需要的Url协议

JS代码:javascript.html

以.html格式放到src/main/assets文件夹里

<!DOCTYPE html>
<html>

  <head>
   <meta charset="utf-8">
   <title>Carson_Ho</title>

   <script>
     function callAndroid(){
      /*约定的url协议为:js://webview?arg1=111&arg2=222*/
      document.location = "js://webview?arg1=111&arg2=222";
     }
   </script>
</head>

<!-- 点击按钮则调用callAndroid()方法 -->
  <body>
   <button type="button" id="button1" onclick="callAndroid()">点击调用Android代码</button>
  </body>
</html>

当该JS通过Android的mWebView.loadUrl("file:///android_asset/javascript.html")加载后,就会回调shouldOverrideUrlLoading (),接下来继续看步骤2:

public class MainActivity extends AppCompatActivity {

  WebView mWebView;
//  Button button;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mWebView = (WebView) findViewById(R.id.webview);

    WebSettings webSettings = mWebView.getSettings();

    // 设置与Js交互的权限
    webSettings.setJavaScriptEnabled(true);
    // 设置允许JS弹窗
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

    // 步骤1:加载JS代码
    // 格式规定为:file:///android_asset/文件名.html
    mWebView.loadUrl("file:///android_asset/javascript.html");

// 复写WebViewClient类的shouldOverrideUrlLoading方法
mWebView.setWebViewClient(new WebViewClient() {
                   @Override
                   public boolean shouldOverrideUrlLoading(WebView view, String url) {

                     // 步骤2:根据协议的参数,判断是否是所需要的url
                     // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
                     //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)

                     Uri uri = Uri.parse(url);
                     // 如果url的协议 = 预先约定的 js 协议
                     // 就解析往下解析参数
                     if ( uri.getScheme().equals("js")) {

                       // 如果 authority = 预先约定协议里的 webview,即代表都符合约定的协议
                       // 所以拦截url,下面JS开始调用Android需要的方法
                       if (uri.getAuthority().equals("webview")) {

                         // 步骤3:
                         // 执行JS所需要调用的逻辑
                         System.out.println("js调用了Android的方法");
                         // 可以在协议上带有参数并传递到Android上
                         HashMap<String, String> params = new HashMap<>();
                         Set<String> collection = uri.getQueryParameterNames();

                       }

                       return true;
                     }
                     return super.shouldOverrideUrlLoading(view, url);
                   }
                 }
    );
  }
    }

特点

优点:不存在方式1的漏洞;

缺点:JS获取Android方法的返回值复杂。

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

// Android:MainActivity.java
mWebView.loadUrl("javascript:returnResult(" + result + ")");

// JS:javascript.html
function returnResult(result){
  alert("result is" + result);
}

方式3:通过 WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息

在JS中,有三个常用的对话框方法:

常用的对话框方法

方式3的原理:Android通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()

方法回调分别拦截JS对话框 (即上述三个方法),得到他们的消息内容,然后解析即可。

下面的例子将用拦截 JS的输入框(即prompt()方法)

说明 :

常用的拦截是:拦截 JS的输入框(即prompt()方法)

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

步骤1:加载JS代码,如下: javascript.html

以.html格式放到src/main/assets文件夹里

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8">
   <title>Carson_Ho</title>

   <script>

  function clickprompt(){
  // 调用prompt()
  var result=prompt("js://demo?arg1=111&arg2=222");
  alert("demo " + result);
}

   </script>
</head>

<!-- 点击按钮则调用clickprompt() -->
  <body>
   <button type="button" id="button1" onclick="clickprompt()">点击调用Android代码</button>
  </body>
</html>

当使用mWebView.loadUrl("file:///android_asset/javascript.html")加载了上述JS代码后,就会触发回调onJsPrompt(),具体如下:

  1. 如果是拦截警告框(即alert()),则触发回调onJsAlert();
  2. 如果是拦截确认框(即confirm()),则触发回调onJsConfirm();

步骤2:在Android通过WebChromeClient复写onJsPrompt()

public class MainActivity extends AppCompatActivity {

  WebView mWebView;
//  Button button;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mWebView = (WebView) findViewById(R.id.webview);

    WebSettings webSettings = mWebView.getSettings();

    // 设置与Js交互的权限
    webSettings.setJavaScriptEnabled(true);
    // 设置允许JS弹窗
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

// 先加载JS代码
    // 格式规定为:file:///android_asset/文件名.html
    mWebView.loadUrl("file:///android_asset/javascript.html");

    mWebView.setWebChromeClient(new WebChromeClient() {
    // 拦截输入框(原理同方式2)
      // 参数message:代表promt()的内容(不是url)
        // 参数result:代表输入框的返回值
      @Override
      public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
        // 根据协议的参数,判断是否是所需要的url(原理同方式2)
        // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
        //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)

        Uri uri = Uri.parse(message);
        // 如果url的协议 = 预先约定的 js 协议
        // 就解析往下解析参数
        if ( uri.getScheme().equals("js")) {

          // 如果 authority = 预先约定协议里的 webview,即代表都符合约定的协议
          // 所以拦截url,下面JS开始调用Android需要的方法
          if (uri.getAuthority().equals("webview")) {

            //
            // 执行JS所需要调用的逻辑
            System.out.println("js调用了Android的方法");
            // 可以在协议上带有参数并传递到Android上
            HashMap<String, String> params = new HashMap<>();
            Set<String> collection = uri.getQueryParameterNames();

            //参数result:代表消息框的返回值(输入值)
            result.confirm("js调用了Android的方法成功啦");
          }
          return true;
        }
        return super.onJsPrompt(view, url, message, defaultValue, result);
      }

// 通过alert()和confirm()拦截的原理相同,此处不作过多讲述

      // 拦截JS的警告框
      @Override
      public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        return super.onJsAlert(view, url, message, result);
      }

      // 拦截JS的确认框
      @Override
      public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
        return super.onJsConfirm(view, url, message, result);
      }
    });
    }
    }

2.2.2 三种方式的对比 & 使用场景

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • Android的WebView与H5前端JS代码交互的实例代码
  • Android webview与js的数据交互
  • Android中webview与JS交互、互调方法实例详解
  • Android总结之WebView与Javascript交互(互相调用)
  • Android WebView使用方法详解 附js交互调用方法
  • Android中WebView与Js交互的实现方法
  • Android WebView上实现JavaScript与Java交互
  • android中WebView和javascript实现数据交互实例
  • android中webview控件和javascript交互实例
  • 解析Android中webview和js之间的交互
(0)

相关推荐

  • Android中WebView与Js交互的实现方法

    获取WebView对象 调用WebView对象的getSettings()方法,获取WebSettings对象 调用WebSettings对象的setJavaScriptEnabled()方法,设置js可用,参数:布尔值 在判断是否支持js的时候,不要用alert(),默认不起作用,可以先用document.write()测试 调用WebView对象的addJavascriptInterface(obj, interfaceName)方法,添加js接口,参数:Object对象,String接口名

  • Android的WebView与H5前端JS代码交互的实例代码

    前段时间项目有深度和前端对接过,也是碰了一些坑,现在有时间就拿出来分享下 JS调用原生不外乎就两种,一种是传假的url,也就是url拦截的方式,类似于下面这种: //js代码 function sendCommand(param){ var url="js-call://"+param; document.location = url; } sendCommand("PlaySnake"); //Java代码 mWebView.setWebViewClient(ne

  • Android WebView上实现JavaScript与Java交互

    其实webview加载资源的速度并不慢,但是如果资源多了,当然就很慢.图片.css .js .html这些资源每个大概需要10-200ms ,一般都是30ms就ok了.不过webview是必须等到全部资源都完成加载,才会进行渲染的,所以加载的速度很重要!从Google上我们了解到,webview加载页面的顺序是:先加载html,然后从里面解析出css.js文件和页面上的图片资源进行加载.如果webkit的缓存里面有,就不加载.加载完这些资源之后,就进行css的渲染和js的执行.Css的渲染一般不

  • Android WebView使用方法详解 附js交互调用方法

    目前很多Android app都内置了可以显示web页面的界面,会发现这个界面一般都是由一个叫做WebView的组件渲染出来的,学习该组件可以为你的app开发提升扩展性. 先说下WebView的一些优点: --可以直接显示和渲染web页面,直接显示网页 --webview可以直接用html文件(网络上或本地assets中)作布局 --和JavaScript交互调用 一.基本使用 首先layout中即为一个基本的简单控件: <WebView android:id="@+id/webView1

  • Android中webview与JS交互、互调方法实例详解

    Android中webview与JS交互.互调方法实例详解 前言: 对于试水的功能,一般公司都会采用H5的方式来开发,可以用很少的资源与很短的项目工期来完成. 但许多情况下,H5页面会需要一些原生持有的一些如用户信息之类的数据,一些交互也需要调用原生的,如toast之类要保持同一个手机风格一致的交互行为.这个时候就需要能够让JS主动调用原生的方法来进行操作或者获取数据.或者是原生调用JS的方法在H5加载的时候传递一些参数. 对于原生调用JS的方法 我们需要实现一个WebViewClient,在这

  • Android总结之WebView与Javascript交互(互相调用)

    前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybrid App居多,单纯的数据展示我们直接采用WebView来渲染就可以了,但是有时候可能会用到两者之间传递参数的情况,今天就来总结一下两者之间如何互相调用.本篇主要介绍WebView与Javascript交互数据,关于如何将H5网页呈现在WebView上可以参考这篇博客文章:Android总结之Web

  • 解析Android中webview和js之间的交互

    1.android中利用webview调用网页上的js代码.Android 中可以通过webview来实现和js的交互,在程序中调用js代码,只需要将webview控件的支持js的属性设置为true,,然后通过loadUrl就可以直接进行调用,如下所示:mWebView.getSettings().setJavaScriptEnabled(true);mWebView.loadUrl("javascript:test()"); 2. 网页上调用android中java代码的方法在网页中

  • android中WebView和javascript实现数据交互实例

    在看懂这篇文章之前首先要有javascript基础. (1) js调用android的方法: 复制代码 代码如下: WebView wView: wView. addJavascriptInterface (Object obj, String interfaceName); 是实例化一个对象,在html的js中调用,第二个参数是实例化对象的别名,如果要使用这个obj,则在js中使用的名字 就是interfaceName. 复制代码 代码如下: public class jsWebDemo ex

  • android中webview控件和javascript交互实例

    当我们要实现丰富的图文混排效果的时候,我们一般会使用webview,这是一个功能十分强大的的控件,来看看官方的解释: 复制代码 代码如下: A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit

  • Android webview与js的数据交互

    项目要用到Webview和js交互,查了查以前的项目感觉还是有必要整理下的. 简单描述下项目中用到的地方,比如说在web页需要用到登录的地方点击登录跳转到APP原生登录界面去登录,点击web页的拨打电话弹出原生dialog询问是否拨打,点击web页里面的图片进行放大处理.针对于上述的需求我们通用的方式大概有两种,一是监听a标签,在shouldOverrideUrlLoading根据URL进行判断,二是js代码注入,找到我们想要处理的元素进行js代码注入.下面就这两种方式简单的进行描述 首先需要初

随机推荐