我尽量不打错别字,用词准确,不造成阅读障碍。
其实很早就接触了这部分知识,只是突然想要梳理一下知识点,感觉写出来要好很多。
Android与JS交互其实是早期混合开发的主要部分,作为混合开发的入门学习和Android开发知识点学习是必要的。而现在的混合开发可以模块化开发中作为一个模块,例如单独用RN写一个模块再集成到app中。
交互分为Android调用JS方法,JS调用Android方法两种,而调用又要考虑有无参数和返回值种情况,所以总共是8种,即Android调用JS方法----有参有返回值、有参无返回值、无参无返回值、无参有返回值。JS调用Android方法----有参有返回值、有参无返回值、无参无返回值、无参有返回值。
效果展示:
上半部分四个按钮是原生代码,下部分四个按钮是js代码。
先做些准备工作:
xml布局文件:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="调用无参无返回值方法"/>
<Button
android:id="@+id/btn2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="调用有参无返回值方法"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="调用无参有返回值方法"/>
<Button
android:id="@+id/btn4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="调用有参有返回值方法"/>
</LinearLayout>
<WebView
android:id="@+id/wv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
html文件(在main文件夹下新建assets文件夹存放此html文件):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
<script type="text/javascript">
<!--android是传过来的对象名称,setMessage是android中的方法-->
var name = "测试参数"
document.getElementById("btn0").onclick = function(){
android.setMessage();
};
document.getElementById("btn1").onclick = function(){
android.setMessage(name);
};
document.getElementById("btn2").onclick = function(){
content.innerHTML = android.setMessage2();
};
document.getElementById("btn3").onclick = function(){
content.innerHTML = android.setMessage2("js参数");
};
var content = document.getElementById("content");
function message(){
content.innerHTML = "调用了无参的js函数"
};
function message2(des){
content.innerHTML = "调用了"+des;
};
function add(){
content.innerHTML = "调用了无参加法方法";
return "无参加法啊";
};
function add2(a,b){
content.innerHTML = "调用了加法方法";
return a+b;
};
</script>
</head>
<body>
<button id="btn0">调用android无参无返回值方法</button>
<button id="btn1">调用android有参无返回值方法</button>
<button id="btn2">调用android无参有返回值方法</button>
<button id="btn3">调用android有参有返回值方法</button>
<div id="content"></div>
</body>
</html>
java部分(省略数据绑定及监听设置):
WebSetting setting = mWebView.getSettings();
setting.setJavaScriptEnabled(true);
mWebView.loadUrl("file:///android_asset/123.html");//注意路径名称的android_asset
Android调用JS方法
首先设置支持js调用
settings.setJavaScriptEnabled(true);
java代码:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1:
//调用无参无返回值方法
mWebView.loadUrl("javascript:message()");
break;
case R.id.btn2:
//在android调用js有参的函数的时候参数要加单引号
//调用有参无返回值方法
mWebView.loadUrl("javascript:message2('" + name + "')");
break;
case R.id.btn3:
//调用无参有返回值方法
mWebView.evaluateJavascript("add()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Toast.makeText(MainActivity.this, "调用了js的无参有返回值的方法,结果为" + value, Toast.LENGTH_SHORT).show();
}
});
break;
case R.id.btn4:
//调用有参有返回值方法
mWebView.evaluateJavascript("add2(4,3)", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Toast.makeText(MainActivity.this, "调用了js的有参有返回值的方法,结果为" + value, Toast.LENGTH_SHORT).show();
}
});
break;
}
}
js代码:
var content = document.getElementById("content");
function message(){
content.innerHTML = "调用了无参的js函数"
};
function message2(des){
content.innerHTML = "调用了"+des;
};
function add(){
content.innerHTML = "调用了无参加法方法";
return "无参加法啊";
};
function add2(a,b){
content.innerHTML = "调用了加法方法";
return a+b;
};
JS调用Android方法
首先要传递一个参数过去
mWebView.addJavascriptInterface(this, "android");
JS那边根据传递过来的"android"关键字调用相应方法。
java代码:
//这个注解必须加 因为 兼容问题
//无参无返回值方法
@JavascriptInterface
public void setMessage() {
Toast.makeText(this, "我弹", Toast.LENGTH_SHORT).show();
}
//有参无返回值方法
@JavascriptInterface
public void setMessage(String name) {
Toast.makeText(this, "我弹弹" + name, Toast.LENGTH_SHORT).show();
}
//无参又返回值方法
@JavascriptInterface
public String setMessage2() {
return "hello world";
}
//有参有返回值方法
@JavascriptInterface
public String setMessage2(String name) {
return "hello " + name;
}
js代码:
<!--android是传过来的对象名称,setMessage是android中的方法-->
var name = "测试参数"
document.getElementById("btn0").onclick = function(){
android.setMessage(); //调用android无参无返回值方法
};
document.getElementById("btn1").onclick = function(){
android.setMessage(name); //调用android有参无返回值方法
};
document.getElementById("btn2").onclick = function(){
//调用android无参又返回值方法,并将返回值打印出来
content.innerHTML = android.setMessage2();
};
document.getElementById("btn3").onclick = function(){
//调用android有参有返回值方法,并将返回值打印出来
content.innerHTML = android.setMessage2("js参数");
};
记录一个小坑:
今天和同事联调,需求是H5会调用一个原生的方法,方法(比如是:aaa())我已写好,@JavascriptInterface 标签也加了,但是就是没有走进这个aaa()方法------即没有调用,后来发现是因为同事重新定义了一个同名对象,将之前的对象覆盖了,新对象没有aaa()方法,奇怪的是,iOS是没问题的,调用aaa()是可以的,所以刚开始双方都觉得自己没问题,笑哭~