概述
Android中可以通过WebView与H5进行交互,然而这其中有诸多细节需要自己去校验实践,下面将逐一介绍android和h5中的细节。
运行效果
技术说明
Android调用JS
mWebView.evaluateJavascript() 4.4以后
loadUrl() 刷新 4.4以前
JS调用Android
mWebView.addJavascriptInterface() 设置回调
原生处理
// 设置方法拦截... (参数1 不清楚, 参数2 交互时相互定义的名字)
mX5WebView.addJavascriptInterface(new JSInterface(),"latte");
private final class JSInterface{
@SuppressLint("JavascriptInterface")
@JavascriptInterface
public void event(String info){
// todo android端对信息进行处理
// 添加我们需要实现具体的原生逻辑处理
// 这里就是我们打开相册的逻辑...
}
}
// 相册回调之后的逻辑处理... 将图片传递给js 进行显示包括进行上传等
// 这里传递的是文件路径
public void showPic(String imagePath){
//todo json传值 将具体的路径传递给js
mX5WebView.evaluateJavascript("javascript:nativeCall(\'"+imagePath+"\');",
new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
//todo
// 接收回传值...
}
});
}
JS中实现
// 在点击事件中: js调用原生方法...
latte.event(JSON.stringify(command));
// 设定js方法以此来提供给原生调用
// 注意: 该方法一定要挂在到window对象上
function nativeCall(text) {
img.src = text;
// 要不然会执行回调2次呢 -- 4.2 以下回传
// window.latte.nativeCall2('哈哈哈哈哈哈');
return "图片切换成功";
}
WebApp虚拟返回键处理
实现按返回键,页面对应的webapp页面回退效果
@Override
public boolean
onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
mWebView.goBack();//返回上个页面
Log.e("地址", mWebView.getUrl());
return true;
}else if (keyCode == KeyEvent.KEYCODE_BACK && !mWebView.canGoBack()){
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(getApplicationContext(), "再按一次退出程序",
Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
实现按返回键,对应的web页面回退,当监测到退无可退时退出应用。之间添加了连续点击返回2次退出应用。
WebView加载web路由并路径传值
需求描述: 像我们的页面,并不是简单加载一个百度网址就完事了,往往我们还需要传递一部分信息过去,例如用户信息 一些状态等。
期望效果: 原生加载url并传递对应的有效数据,web端页面负责接收数据并进行数据加载,原生与web需要相互协作
// android端负责传递数据
mWebView.loadUrl("https://app.wjsci.com/#/newLogin?age=1&name=ming");
// vue端负责接收数据
created(){
if (isAndroid && IS_BUILDING){
let params = this.$route.query;
console.log(params.age);
console.log(params.name);
},
webview页面加载失败
mWebView.setWebViewClient(new WebViewClient(){
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
isError = false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view,url);
cancelNiceDialog();
if (!isError) {
isSuccess = true;
if (mWebView.getVisibility() == View.INVISIBLE){
mWebView.setVisibility(View.VISIBLE);
}
isError = false;
return;
}
// 失败的处理
mWebView.setVisibility(View.INVISIBLE);
mRlError.setVisibility(View.VISIBLE);
isError = false;
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
isError = true;
isSuccess = false;
}
});
页面实现效果,加载过程中显示加载进度条,在加载失败后显示对应加载失败的页面,用户也可以点击进行重新加载。
需要警醒的内容
经过我一个webapp的开发经验来看,还是推荐大家使用Android原生的WebView,我需要指出的有2点,抛开生产商来说,google技术应当毋庸置疑,人家该优化该适应手机的都会考虑到吧。然而X5浏览器确存在着软键盘弹出收缩的兼容性问题。就开发而言还是推荐大家能够使用我们默认的浏览器。
补充内容
vue 回调ios退出页面
if (isIphone && IS_BUILDING){
// 页面退出....
window.webkit.messageHandlers.backPage.postMessage(0);
}
vue调用ios方法
window.webkit.messageHandlers.callLoginOut.postMessage(0);
如上图所示只需调用ios提供给web 调用的js即可
规避webview造成的内存泄漏
@Override
protected void onDestroy() {
if (webView != null) {
webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
webView.clearHistory();
ViewGroup parent = (ViewGroup) webView.getParent();
if (parent != null) {
parent.removeView(webView);
}
webView.removeAllViews();
webView.stopLoading();
webView.setWebChromeClient(null);
webView.setWebViewClient(null);
webView.destroy();
webView = null;
}
super.onDestroy();
}
webview优化学习
Android:你所忽略 WebView 带来的那些安全漏洞(总结)
webview内存泄漏处理