在移动开发中,有关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再分享出来,谢谢。