在移动开发中,有关Native与H5交互的场景和应用越来越多,相对于app开发成本偏大和热度逐渐降低,前端H5的应用开就发显得更受欢迎。公司Native转H5开化就是一个很好的证明。但是有些Native的技术毕竟是H5无法取代的(比方说拨号打电话、拍照片和读写文件等),而且H5的页面也必须的有一个容器来解释执行它,由此就出现了Native和H5的混合开发,混合模式开发的App可以说占据了主流应用市场。 下面就来详细介绍一下Android与H5交互的具体应用实现:
1、Android中WebView加载H5页面,这个不多说,直接贴代码:
//加载assets目录下的js_call_android.html文件
webView.loadUrl("file:///android_asset/js_call_android.html");
//加载远程URL:https://www.baidu.com
webView.loadUrl("https://www.baidu.com");
//加载远程URL:https://www.baidu.com,自定义请求Header
Map<String,String> headers = new HashMap<String,String>();
headers.put("Referer", "http://www.google.com");
headers.put("token","token113234");
webView.loadUrl("https://www.baidu.com",null);
//使用loadData方法加载数据
String htmlData = "<html><body>你好!</body></html>";
String mimeType = "text/html;charset=UTF-8";
String encoding = "UTF-8";
webView.loadData(htmlData,mimeType,encoding);
2、Android调用H5中js方法 Android中调用JS无非两种方式,WebView.loadUrl() 和 WebView.evaluateJavascript() 下面是具体实例:
WebSettings webSettings = webView.getSettings();
// 告诉WebView启用JavaScript执行。默认的是false。
webSettings.setJavaScriptEnabled(true);
//Android调用js中的无参数无返回值的函数方式
webView.loadUrl("javascript:noParamMessage()");
//Android调用js中的有参数无返回值的函数方式
webView.loadUrl("javascript:hasParamMessage('" + name + "')");
//Android调用js中的无参数有返回值的函数方式,仅支持android4.4及以上sdk
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript("javascript:noParamReturn()", new ValueCallback<String>() {
[@Override]()
public void onReceiveValue(String s) {
Toast.makeText(MainActivity.this,"调用js函数返回值:" + s,Toast.LENGTH_SHORT).show();
}
});
}
//Android调用js中的有参数有返回值的函数方式,仅支持android4.4及以上sdk
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript("javascript:hasParamReturn(100,80)", new ValueCallback<String>() {
[@Override]()
public void onReceiveValue(String s) {
Toast.makeText(MainActivity.this,"调用js函数返回值:" + s.toString(),Toast.LENGTH_SHORT).show();
}
});
}
3、H5中JS调用Android,应该说是JS与Android交互更准确。JS与Android的交互方式总共有三种:
3.1 WebView.addJavascriptInterface(),这种方式会有安全和版本兼容性问题。
首先创建一个类,这个类有些特殊,所有给H5调用的方法必须加上@JavascriptInterface注解:
public class JsCallAndroid {
private static final String TAG = "JsCallAndroid.";
/**
* 暴露给js调用的无参数方法
*/
@JavascriptInterface
public void callNoParamMethod(){
Log.i("callNoParamMethod","js调用了android无参数的方法!");
}
/**
* 暴露给js调用的有参数方法
*/
@JavascriptInterface
public void callWithParam(String name){
Log.i("callWithParam","js调用了android有参数的方法!参数:" + name);
}
}
接着用上面的类new一个对象并取别名为android(这个别名可以随便取,只要符合js中的命名规则即可)注册到window上:
WebView.addJavascriptInterface(new JsCallAndroid(), "android" )
最后在JS中就可以直接调用了
window.android.callWithParam('param')
window.android.callNoParamMethod()
3.2 WebViewClient.shouldOverrideUrlLoading(),这种方式比较通用,通过超链接或者iframe的src值的变化,把消息封装在url schema中,达到与Android交互信息的目的。其中的url schema可以自定义,比较自由。
首先重写WebViewClient.shouldOverrideUrlLoading方法:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i("WebViewClient",url);
if(url.contains("www.baidu.com")) {
view.loadUrl(url);
return true;
}else if(url.contains("xxy")){
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view,url);
}
H5中调用(超链接方式):
<a href='xxy://localhost/scheme_activity'>Scheme跳转到Activity</a></br></br>
<a href='https://www.baidu.com'>百度</a></br></br>
H5中调用(iframe修改src的值方式),看过一些文档JsBridge框架就是采用的这种方式。
function simulateUrlChange(){
document.getElementById("js_iframe").src="xxy://localhost/scheme_activity";
};
3.3 通过WebChromeClient.onJsAlert()/onJsConfirm()/onJsPrompt() 方法分别回调拦截JS对话框alert()、confirm()、prompt()消息,大家从方法也可以看出它们之间的关系。
重写WebChromeClient.onJsAlert()/onJsConfirm()/onJsPrompt() 方法
webView.setWebChromeClient(new WebChromeClient(){
/**
* 处理H5页面的 alert(params)方法
* @param view
* @param url
* @param message
* @param result
* @return
*/
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.i("onJsAlert",url);
Log.i("onJsAlert",message);
return super.onJsAlert(view, url, message, result);
}
/**
* 处理H5页面的 comfirm(params)方法
* @param view
* @param url
* @param message
* @param result
* @return
*/
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
Log.i("onJsConfirm",url);
Log.i("onJsConfirm",message);
return super.onJsConfirm(view, url, message, result);
}
/**
* 处理H5页面的 prompt(param1,param2)方法
* @param view
* @param url
* @param message
* @param defaultValue
* @param result
* @return
*/
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
Log.i("onJsPrompt",url);
Log.i("onJsPrompt",message);
Log.i("onJsPrompt",defaultValue);
return super.onJsPrompt(view, url, message, defaultValue, result);
}
});
JS调用alert、comfirm和prompt方法:
function callAlert(){
alert("alert方法");
}
function callConfirm(){
confirm("confirm方法");
}
function callPrompt(){
prompt("prompt方法","default value");
}
好了,Android与H5的交互就分享到这里,后续实现了自己的JsBridge再分享出来,谢谢。