越来越多的应用采用原生代码与Html混合开发的方式,对于这种类型的应用,Android如何与JS进行交互呢?本篇就对交互方式进行总结。
这边先列下各种交互方式:
一、WebView加载Html
加载Html的方式这里简单列一下,webview的设置这边不做详细讲解。
//加载assets里的test.html
mWebView.loadUrl("file:///android_asset/test.html");
//加载网页
mWebView.loadUrl("https://www.baidu.com/");
二、Android调用Html里的JS方法
1、通过WebView的loadUrl () 方法调用JS方法
调用方式:WebView.loadUrl("javascript:<方法名>(<有参数时传参>)");
具体代码:
public class MainActivity extends AppCompatActivity {
WebView mWebView;
Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = findViewById(R.id.wv);
mButton = findViewById(R.id.btn);
// 获取WebSetting对象
WebSettings webSettings = mWebView.getSettings();
// 设置支持javascript
webSettings.setJavaScriptEnabled(true);
// 设置允许JS弹窗
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.setWebChromeClient(new WebChromeClient());
//加载assets里的test.html
mWebView.loadUrl("file:///android_asset/test.html");
//加载网页
//mWebView.loadUrl("https://www.baidu.com/");
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//调用js要在webview加载完才可以调用
mWebView.post(new Runnable() {
@Override
public void run() {
//方法名fucn1要写对,传入的参数要用单引号或双引号引用,双引号注意要用转义字符
mWebView.loadUrl("javascript:func1('a1a')");
}
});
}
});
}
}
test.html代码:
该种方式简单但是获取JS返回值较麻烦。
2、通过WebView的evaluateJavascript ()方法调用JS方法(可以获取返回值)
只需要将loadUrl()换成下面该方法即可
mWebView.evaluateJavascript("javascript:func1('a1a')", new ValueCallback() {
@Override
public void onReceiveValue(String value) {//value为 js 返回的值
}
});
该方法在android版本19以下不能使用,所以最好配合方法1使用,如下:
if(Build.VERSION.SDK_INT() {
@Override
public void onReceiveValue(String value) {//value为 js 返回的值
}
});
}
三、JS调用Android代码
1、通过WebView的addJavascriptInterface () 进行对象映射
首先,定义一个要被JS调用的类,被调用的方法加@JavascriptInterface注解。
public class CallByJS{
// 被JS调用的方法必须加@JavascriptInterface注解
@JavascriptInterface
public void callByJS(String str) {
Log.e("web_test",str);
}
}
然后在WebView里通过addJavascriptInterface()将Java对象映射到JS对象。
// 通过addJavascriptInterface()将Java对象映射到JS对象
mWebView.addJavascriptInterface(new CallByJS(), "androidObj");
接下来JS就可以通过androidObj调用CallByJS对象的方法了。
运行,点击调用按钮
Logcat里日志如下,说明JS调用了android的代码。
2、通过 WebViewClient 的shouldOverrideUrlLoading ()方法拦截 url。
这种方式就是Android通过 WebViewClient 的回调方法shouldOverrideUrlLoading ()拦截 url,解析该 url 的协议,如果检测到是预先约定好的协议,就执行相应方法 。
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 根据协议的参数进行拦截,下面拦截"callandroid://test"
// 一般根据scheme & authority判断
Uri uri = Uri.parse(url);
// 如果 scheme = callAndroid,即代表都符合约定的协议
if (uri.getScheme().equals("callandroid")) {
// 如果 authority = test,即代表都符合约定的协议
if (uri.getAuthority().equals("test")) {// 拦截url,下面开始执行Android的方法
Toast.makeText(MainActivity.this, "js通过拦截调用了Android的方法", Toast.LENGTH_SHORT).show();
// 可以获取参数
HashMap params = new HashMap<>();
Set paramNames = uri.getQueryParameterNames();
for (String name : paramNames) {
params.put(name, uri.getQueryParameter(name));
}
Log.e("web-test", params.toString());
}
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
});
接下来在Html里调用,下面的clickBtn2()方法:
运行程序,点击第二个按钮,执行shouldOverrideUrlLoading方法,链接被拦截,开始执行对应的业务逻辑代码:
也可以获取参数,Logcat打印出参数如下:
该方法JS无法直接获取android代码的返回值,需要android调用JS方法的方式把返回值传给JS。
3、通过 WebChromeClient 的onJsAlert ()、onJsConfirm ()、onJsPrompt ()方法拦截JS对话框alert ()、confirm ()、prompt ()消息
该方式就是Android通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法分别拦截JS的alert(),confirm(),prompt()弹出框。
下面写个onJsPrompt()拦截prompt()的例子。
首先重写onJsPrompt方法,拦截方式与方式2类似。
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
return super.onJsConfirm(view, url, message, result);
}
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// 根据协议的参数进行拦截,下面拦截"callandroid://test"
// 一般根据scheme & authority判断
Uri uri = Uri.parse(message);//message是由JS的prompt()传来的
// 如果 scheme = callAndroid,即代表都符合约定的协议
if (uri.getScheme().equals("callandroid")) {
// 如果 authority = test,即代表都符合约定的协议
if (uri.getAuthority().equals("test")) {// 拦截url,下面开始执行Android的方法
// 可以获取参数
HashMap params = new HashMap<>();
Set paramNames = uri.getQueryParameterNames();
for (String name : paramNames) {
params.put(name, uri.getQueryParameter(name));
}
//将返回值返回给JS
result.confirm("拦截Prompt成功啦,传进来的参数是:"+params.toString());
}
return true;
}
return super.onJsPrompt(view, url, message, defaultValue, result);
}
});
接下来在Html用JS调用
执行代码,点击按钮3:
其他两个方法拦截也类似,只不过alert ()没有返回值,confirm ()返回值是boolean类型。
项目源码地址:https://gitee.com/wiggins/WebviewJsTest.git