Android WebView与Js的交互

Android调用JS中的方法

  1. view.loadUrl(“javascript:callJs(\”Android传递数据给js\”);”);
  2. view.evaluateJavascript

在html中有以下内容:

 //Android需要调用的方法,str由Android端传递来
   function callJs(str){
      alert("Android调用了JS的callJS方法,获得来自Android端的数据:"+str);
   }

    //Android需要调用的方法,str由Android端传递来,此函数的返回值由Android端接收
   function callJsByEval(str){
      alert("Android调用了JS的callJS方法,获得来自Android端的数据:"+str);
      return "js 返给 Android";
   }

在Android端

在Activity的onCreate中调用
webView.loadUrl("http://192.168.0.164:8080/bootstrap_sign_in.html");
WebSettings mSettings = webView.getSettings();
mSettings.setJavaScriptEnabled(true);//开启javascript
webView.setWebViewClient(new Clientweb());

//继承WebClient的类

private class Clientweb extends WebViewClient{
    /**
     * 页面加载完成回调的方法
     */
    @Override
    public void onPageFinished(final WebView view, String url) {
        super.onPageFinished(view, url);
        //JS代码调用一定要在 onPageFinished() 回调之后才能调用,否则不会调用
        //4.4以下使用此方法  无法获得js的返回值
        view.loadUrl("javascript:callJs(\"Android传递数据给js\");");
        //4.4以上使用此方法,可以获得js的返回值
        view.evaluateJavascript("javascript:callJsByEval(\"Android传递数据给js eval\")", new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String value) {
                //此处为 js 返回的结果
                Toast.makeText(view.getContext(),value,Toast.LENGTH_LONG).show();
            }
        });
    }
    }

JS调用Android代码

  1. 使用注解@JavascriptInterface
  2. 在shouldOverrideUrlLoading里面拦截url
  3. 在onJsPrompt,onJsAlert,onJsConfirm里面拦截url
使用注解@JavascriptInterface

新建一个类,需要js调用的方法要加上注解@JavascriptInterface,如下所示:

import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.Toast;

public class Js {
    private WebView webView;
    public Js(WebView webView) {
        this.webView = webView;
    }
    @JavascriptInterface
    public void showA(String intentid_str) {
        Toast.makeText(webView.getContext(),intentid_str,Toast.LENGTH_LONG).show();
    }

    @JavascriptInterface
    public void showB(String intentid_str) {
        Toast.makeText(webView.getContext(),intentid_str,Toast.LENGTH_LONG).show();
    }
}

通过WebView调用:

webView.loadUrl("http://192.168.0.164:8080/bootstrap_sign_in.html");
WebSettings mSettings = webView.getSettings();
mSettings.setJavaScriptEnabled(true);//开启javascript
webView.setWebViewClient(new Clientweb());
Js  javaJs=new Js(webView);
webView.addJavascriptInterface(javaJs,"external");

html中对应的内容,相关的字符串必须保持一致,比如这里的external,showA,showB

 <button  type="submit" onclick="callAndroid()">Sign in</button>
      <p><a href="javascript:window.external.showA('js调用Android中的showA方法');">2017-2018</a></p>

function callAndroid(){
       external.showB("js调用了android中的showB方法");
    }
在shouldOverrideUrlLoading里面拦截url
 public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            Uri uri = Uri.parse(request.getUrl().toString());
            // 通过解析Uri进行逻辑判断,只对预先协商好的协议响应
            if ( uri.getScheme().equals("js")) {
                if (uri.getAuthority().equals("method1")) {//响应协议上的method1方法:js://method1?arg1=111&arg2=222
                    // 获取js传递过来的参数
                    Set<String> collection = uri.getQueryParameterNames();
                    StringBuilder stringBuilder=new StringBuilder();
                    for (String str : collection) {
                        stringBuilder.append(str);
                        stringBuilder.append(":");
                        stringBuilder.append(uri.getQueryParameter(str));
                        stringBuilder.append(",");
                    }
                    Toast.makeText(view.getContext(),"js调用了Android的方法,获取的js传递的参数是:"+stringBuilder.toString().substring(0,stringBuilder.toString().length()-1),Toast.LENGTH_LONG).show();
                }else if(uri.getAuthority().equals("method2")){  //响应协议上的method1方法:js://method2?arg1=111&arg2=222
                    // 获取js传递过来的参数
                    Set<String> collection = uri.getQueryParameterNames();
                    StringBuilder stringBuilder=new StringBuilder();
                    for (String str : collection) {
                        stringBuilder.append(str);
                        stringBuilder.append(":");
                        stringBuilder.append(uri.getQueryParameter(str));
                        stringBuilder.append(",");
                    }
                    Toast.makeText(view.getContext(),"js调用了Android的方法,获取的js传递的参数是:"+stringBuilder.toString().substring(0,stringBuilder.toString().length()-1),Toast.LENGTH_LONG).show();
                }
                return true;
            }
            return super.shouldOverrideUrlLoading(view, request);
        }
在onJsPrompt,onJsAlert,onJsConfirm里面拦截url
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
            Uri uri = Uri.parse(message);
            // 通过解析Uri进行逻辑判断,只对预先协商好的协议响应
            if ( uri.getScheme().equals("js")) {
                if (uri.getAuthority().equals("prompt")) {//响应协议上的prompt方法:js://prompt?arg1=111&arg2=222
                    // 获取js传递过来的参数
                    Set<String> collection = uri.getQueryParameterNames();
                    StringBuilder stringBuilder=new StringBuilder();
                    for (String str : collection) {
                        stringBuilder.append(str);
                        stringBuilder.append(":");
                        stringBuilder.append(uri.getQueryParameter(str));
                        stringBuilder.append(",");
                    }
                    result.confirm("js调用了Android的方法,获取的js传递的参数是:"+stringBuilder.toString().substring(0,stringBuilder.toString().length()-1));
                    //Toast.makeText(view.getContext(),"js调用了Android的方法,获取的js传递的参数是:"+stringBuilder.toString().substring(0,stringBuilder.toString().length()-1),Toast.LENGTH_LONG).show();
                }
                return true;
            }
            return super.onJsPrompt(view, url, message, defaultValue, result);
        }
使用到了html的关键代码
<body class="text-center">
    <form class="form-signin">
      <img class="mb-4" src="bootstrap-solid.svg" alt="" width="72" height="72">
      <h1 class="h3 mb-3 font-weight-normal"  onclick="clickprompt();">拦截prompt调用Android端方法</h1>
      <label for="inputEmail" class="sr-only">Email address</label>
      <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>
      <label for="inputPassword" class="sr-only">Password</label>
      <input type="password" id="inputPassword" class="form-control" placeholder="Password" required>
      <div class="checkbox mb-3">
        <label>
          <input type="checkbox" value="remember-me" onchange="toggleCheckbox(this)">响应服务端的alert
        </label>
      </div>
      <button class="btn btn-lg btn-primary btn-block" type="submit" onclick="callAndroid()">注解调用Android端方法1</button>
      <p class="text-muted"><a href="javascript:window.external.showA('js调用Android中的showB方法');">注解调用Android端方法2</a></p>

      <p class="text-muted"><a href="js://method1?arg1=111&arg2=222">拦截url调用Android端方法1</a></p>

      <p class="text-muted"><a href="js://method2?arg1=中国&arg2=天数奇谭">拦截url调用Android端方法2</a></p>
    </form>

    <script>
      function toggleCheckbox(element){
        var aa=element.checked;
        var s=aa ? "选中了" : "取消了";
        alert(s);
      }

    //Android需要调用的方法
   function callJs(str){
      alert("Android调用了JS的callJS方法,获得来自Android端的数据:"+str);
   }

    //Android需要调用的方法
   function callJsByEval(str){
      alert("Android调用了JS的callJS方法,获得来自Android端的数据:"+str);
      return "js 返给 Android";
   }

    function callAndroid(){
       external.showA("js调用了android中的showA方法");
    }

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

参考:
https://blog.csdn.net/carson_ho/article/details/64904691?locationNum=2

猜你喜欢

转载自blog.csdn.net/cdc_csdn/article/details/80715296