安卓webview原生和JavaScript(js)交互传值的4种方式 java和js交互 安卓JsBridge原理解析

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();

}




[]( )一,addJavascriptInterface 实现js调用安卓

==============================================================================================



*   针对Android 4.2(API 17)及以上

*   js可以调用安卓方法

*   通过调用安卓方法可以实现安卓向js传递数据

*   要被js调用的方法必须加@JavascriptInterface注释

*   使用这个方法前必须设置webview.getSettings().setJavaScriptEnabled(true);



> 主要通过  

> public void addJavascriptInterface(Object object, String name) {}方法实现js调用安卓原生代码,简单讲解下两个参数。  

> object:安卓对象  

> name:安卓对象的别名。  

> 如我们定义  

> webview.addJavascriptInterface(JavaH5Activity.this, “androidObject”);就是把JavaH5Activity的实例命名为androidObject传递给js。  

> 我们在js里的调用如下



完整代码如下:



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的代码如下






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

如下图  

![手机运行效果](https://upload-images.jianshu.io/upload_images/6273713-5665598532714e84.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  

![log日志](https://upload-images.jianshu.io/upload_images/6273713-2ca4fb794b770748.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  

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



@JavascriptInterface

public String androidMethod() {

    Log.i("qcl0228", "js调用了安卓的方法");

    return "我是js调用安卓获取的数据";

}




[]( )二,shouldOverrideUrlLoading 实现js调用安卓

------------------------------------------------------------------------------------------------



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

简单的重定向的代码如下






这里的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编码](https://upload-images.jianshu.io/upload_images/6273713-c8b437cd5486f961.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  

安卓端的代码做拦截解析。



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;

        }

    });



打印结果如下  

![日志](https://upload-images.jianshu.io/upload_images/6273713-58cd08b51fce74bf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  

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



[]( )三,loadUrl:安卓调用js

-----------------------------------------------------------------------------



*   安卓通过webview的loadUrl可以调用js方法

*   安卓传递数据给js

*   js不能返回数据,因为js返回数据的话,会导致重定向问题。下面会做讲解。  

    安卓端的代码如下



String jsonParams = “123456”;

//String url = “javascript:jsMethod()”;//不拼接参数,直接调用js的jsMethod函数

String url = “javascript:jsMethod(” + jsonParams + “)”;//拼接参数,就可以把数据传递给js

webview.loadUrl(url);




js的代码如下:






运行结果如下  

![运行结果](https://upload-images.jianshu.io/upload_images/6273713-2492393af5edb7e3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  

可以看到我们把数据jsonParams传递给了js并显示在了h5页面上。  

上js代码里的 //return ‘987654321’;注释如果解开,会发生请求重定向的问题,如下图  

![image.png](https://upload-images.jianshu.io/upload_images/6273713-9a1e49f2b1ba9900.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  

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



[]( )四,evaluateJavascript:安卓调用js

----------------------------------------------------------------------------------------



*   必须大于api19(4.4)才可以使用

*   可以实现安卓和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);

    }

});

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值