互联网科技IT@程序员猿媛【学】@Jav...

安卓webview原生和JavaScript(js)交互传值的4

2019-02-28  本文已影响3人  编程小石头666

JsBridge:安卓和javascript最流行的交互方式,有以下4种方式可以实现交互传值

js调用安卓

安卓调用js

下面我门结合代码具体讲解下这4中方式的具体代码实现

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>Untitled Document</title>
</head>
<body>
<div id="div" onclick="getAndroidValue()"style="width:100px; height:100px; background-color:#099;"></div>
<script type="text/javascript">
function chongdingxiang(){
   //模拟重定向
   window.location.href="qiushi://setH5Info?params=%7B%22title%22%3A%22%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%22%7D";
}
function jsMethod(jsonParams){
   document.getElementById("div").style.backgroundColor='red';
   document.getElementById("div").innerHTML=jsonParams;
   return '987654321';
}
function getAndroidValue(){
 document.getElementById("div").innerHTML=window.androidObject.androidMethod();
}
</script>
</body>

</html>

一,addJavascriptInterface 实现js调用安卓

主要通过
public void addJavascriptInterface(Object object, String name) {}方法实现js调用安卓原生代码,简单讲解下两个参数。
object:安卓对象
name:安卓对象的别名。
如我们定义
webview.addJavascriptInterface(JavaH5Activity.this, "androidObject");就是把JavaH5Activity的实例命名为androidObject传递给js。
我们在js里的调用如下
<div id="div" onclick="window.androidObject.androidMethod()"></div>

完整代码如下:

public class JavaH5Activity extends AppCompatActivity {
    private WebView webview;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_java_h5);
        webview = findViewById(R.id.webview);
        String url = "file:///android_asset/h5demo2.html";
        webview.loadUrl(url);
        //1,js调用安卓
        webview.getSettings().setJavaScriptEnabled(true);//这里必须开启
        //把当前JavaH5Activity对象作为androidObject别名传递给js
        //js通过window.androidObject.androidMethod()就可以直接调用安卓的androidMethod方法
        webview.addJavascriptInterface(JavaH5Activity.this, "androidObject");
    }

    //js调用安卓,必须加@JavascriptInterface注释的方法才可以被js调用
    @JavascriptInterface
    public String androidMethod() {
        Log.i("qcl0228", "js调用了安卓的方法");
        return "我是js调用安卓获取的数据";
    }
}

js的代码如下

<body>
<div id="div" onclick="getAndroidValue()"style="width:100px; height:100px; background-color:#099;"></div>
<script type="text/javascript">
function getAndroidValue(){
 document.getElementById("div").innerHTML=window.androidObject.androidMethod();
}
</script>
</body>

在js里我们使用window.androidObject.androidMethod();调用安卓的方法,进而获取到安卓传递过来的数据。
如下图


手机运行效果
log日志

同时看日志,我们能看到js成功的调用了安卓的方法,并获取到了安卓native传递过来的数据。

@JavascriptInterface
  public String androidMethod() {
        Log.i("qcl0228", "js调用了安卓的方法");
        return "我是js调用安卓获取的数据";
   }

二,shouldOverrideUrlLoading 实现js调用安卓

js通过重定向出发安卓拦截,重定向的url被shouldoverrideurlloading拦截到。分发拦截到的信息指挥安卓做事情。
简单的重定向的代码如下

<div id="div" onclick="chongdingxiang()"style="width:100px; height:100px; background-color:#099;"></div>
<script type="text/javascript">
function chongdingxiang(){
   //模拟重定向
   window.location.href="qiushi://setH5Info?params=%7B%22title%22%3A%22%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%22%7D";
}
</script>

这里的url:“qiushi://setH5Info?params=%7B%22title%22%3A%22%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%22%7D”是url编码后的,编码前的样式如下。这里涉及到url传递汉子需要编码的问题。以后有机会再做url编码的讲解。

URL编码
安卓端的代码做拦截解析。
 webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Log.i("qcl0228", "拦截到的url:" + url);
                //url如果以qiushi开头,就是h5和我们定义的传值协议
                if (url.startsWith("qiushi")) {
                    Uri uriRequest = Uri.parse(url);
                    String scheme = uriRequest.getScheme();
                    String action = uriRequest.getHost();
                    String query = uriRequest.getQuery();
                    if ("qiushi".equals(scheme)) {
                        if (!TextUtils.isEmpty(query)) {
                            //把url携带的参数存到一个map里
                            HashMap maps = new HashMap();
                            Set<String> names = uriRequest.getQueryParameterNames();
                            for (String name : names) {
                                maps.put(name, uriRequest.getQueryParameter(name));
                            }
                            JSONObject jsonObject = new JSONObject(maps);
                            if ("setH5Info".equals(action)) {
                                if (jsonObject != null && jsonObject.has("params")) {
                                    String h5InfoParams = jsonObject.optString("params");
                                    Log.i("qcl0228", "拦截到的参数:" + h5InfoParams);
                                }
                            }
                        }
                    }
                } else {
                    view.loadUrl(url);
                }
                return true;
            }
        });

打印结果如下


日志

这里我们可以看到安卓成功拦截到了url并解析出来了url里的数据,这样js就可以通过这些数据指挥安卓做事情了。并且也可以做到js传递数据给安卓的效果。

三,loadUrl:安卓调用js

String jsonParams = "123456";
 //String url = "javascript:jsMethod()";//不拼接参数,直接调用js的jsMethod函数
String url = "javascript:jsMethod(" + jsonParams + ")";//拼接参数,就可以把数据传递给js
 webview.loadUrl(url);

js的代码如下:

<div id="div" style="width:100px; height:100px; background-color:#099;"></div>
<script type="text/javascript">
function jsMethod(jsonParams){
   document.getElementById("div").style.backgroundColor='red';
   document.getElementById("div").innerHTML=jsonParams;
   //return '987654321';//如果返回数据,会重定向
}
</script>

运行结果如下


运行结果

可以看到我们把数据jsonParams传递给了js并显示在了h5页面上。
上js代码里的 //return '987654321';注释如果解开,会发生请求重定向的问题,如下图


image.png
这里不能通过安卓调用js代码获取js数据,那该怎么办呢,下面的方法正好可以弥补这个缺陷。

四,evaluateJavascript:安卓调用js

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    String jsonParams = "123456";
    //String method = "jsMethod()";//不拼接参数,直接调用js的jsMethod函数
    String method = "jsMethod(" + jsonParams + ")";//拼接参数,就可以把数据传递给js
    webview.evaluateJavascript(method, new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            Log.i("qcl0228", "js返回的数据" + value);
        }
    });
}

js的代码如下

<div id="div" style="width:100px; height:100px; background-color:#099;"></div>
<script type="text/javascript">
function jsMethod(jsonParams){
   document.getElementById("div").style.backgroundColor='red';
   document.getElementById("div").innerHTML=jsonParams;
   return '987654321';//如果返回数据,会重定向
}
</script>

运行结果如下


运行结果

打印日志如下


image.png
我们可以看到,通过evaluateJavascript可以实现安卓调用js代码。并且安卓的数据可以传递给js,js的数据也可以传递给安卓。

JSBridge的原理解析

JSBridge:是一座用JavaScript搭建起来的桥,替代了WebView的自带的JavascriptInterface的接口,使得我们的开发更加灵活和安全。一端是web,一端是native,他可以根据web和native约定好的规则来通知native要做什么,从而实现Android和Javascript之间的交互

JSBridge的原理可以总结为以下三点:

上一篇下一篇

猜你喜欢

热点阅读