安卓原生和js交互的4种方式 java和js交互 安卓JsBridge原理解析

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

1,addJavascriptInterface:针对Android 4.2(API 17)及以上,只有标有@JavascriptInterface注解的public方法才能从js调用。而对targetSdkVersion为API Level 16及以下的app,js可以调用Java所有的public方法。通过public void addJavascriptInterface (Object object, String name)方法把对象传递给js,2, loadUrl:可以实现安卓调用js,通过webview.loadUrl("javascript:jsMethod()");字符串里的javascript: 是固定写法,后面的jsMethod可以替换成你js代码里的方法。也可以通过"javascript:jsMethod(" + jsonParams + ")";传递数据给js。这个缺点:如果js方法返回数据,这里会发生重定向解决办法是用evaluateJavascript3,evaluateJavascript:安卓4.4以后可以实现安卓调用js,安卓可以传数据给js,并且可以获取js方法的返回值。缺点:必须大于api19(4.4)才可以使用4,shouldOverrideUrlLoading:通过这个方法拦截url,并解析url携带的参数,如:qiushi://setH5Info?params={"title"%3A"商品详情"}

js调用安卓

webView.addJavascriptInterface()WebViewClient.shouldOverrideUrlLoading()

安卓调用js

webView.loadUrl();webView.evaluateJavascript()

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

首先我们要在androidstudio的assets文件夹下面定义下面html。

<!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()"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调用安卓

针对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里的调用如下

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

安卓通过webview的loadUrl可以调用js方法安卓传递数据给jsjs不能返回数据,因为js返回数据的话,会导致重定向问题。下面会做讲解。安卓端的代码如下String jsonParams = "123456";

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

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

webview.loadUrl(url);

js的代码如下:

<div id="div" 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';注释如果解开,会发生请求重定向的问题,如下图

这里不能通过安卓调用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);

}

});

}

js的代码如下

<div id="div" 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>

运行结果如下

运行结果

打印日志如下

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

JSBridge的原理解析

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

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

1、Android通过loadUrl(url)调用JS对象,可以在URL内传递参数。2、JS调用Android是通过shouldOverrideUrlLoading拦截uri。3、JsBridge将数据封装成Message,然后放进Queue,再将Queue通过协议进行传输。

有任何关于编程的问题都可以私信我,我看到后会及时解答。

编程小石头,码农一枚,非著名全栈开发人员。分享自己的一些经验,学习心得,希望后来人少走弯路,少填坑。

编程小石头,为分享干货而生!据说,每个年轻上进,颜值又高的互联网人都关注了编程小石头。

相关文章

应用场景 C端用户提交工单、工单创建完成之后、会发布一条工...
线程类,设置有一个公共资源 package cn.org.chris.concurre...
Java中的数字(带有0前缀和字符串)
在Java 9中使用JLink的目的是什么?
Java Stream API Filter(过滤器)
在Java中找到正数和负数数组元素的数量