Android(安卓)WebView 踩过的坑
16lz
2021-01-26
首先wenview大家都知道的一些API
WebChromeClient是辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等 :
onCloseWindow(关闭WebView) onCreateWindow() onJsAlert (WebView上alert是弹不出来东西的,需要定制你的WebChromeClient处理弹出) onJsPrompt onJsConfirm onProgressChanged onReceivedIcon onReceivedTitle
- WebView 文件上传,直接看代码:
webView.setWebChromeClient(new MyWebChromeClient());
private ValueCallback mUploadCallbackAboveL;private ValueCallback mUploadMessage;private class MyWebChromeClient extends WebChromeClient { // For Android 3.0+ public void openFileChooser(ValueCallback uploadMsg, String acceptType) { if (mUploadMessage != null) return; mUploadMessage = uploadMsg; showPhotoView(); } // For Android < 3.0 public void openFileChooser(ValueCallback uploadMsg) { openFileChooser(uploadMsg, ""); } // For Android > 4.1.1 public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg, acceptType); } // For Android 5.0+ public boolean onShowFileChooser (WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { if (mUploadCallbackAboveL != null){ return false; } mUploadCallbackAboveL = filePathCallback; showPhotoView(); return true; } }
/** * 自定义的文件选择框,包括相机 图库 */ private void showPhotoView() { photoSelectFragment = new PhotoSelectFragment(); photoSelectFragment.setOnPhotoListItemClickListener(this); photoSelectFragment.setOnDismissListener(this); photoSelectFragment.show(getSupportFragmentManager(), "photoSelectFragment"); }
当文件选择的dialog消失时或者取消时要调用以下代码,否则就会出现再次点击不再弹出选择dialog:
/** * 重置 mUploadMessage */ private void clearUploadCallBack(){ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {//5.0以下 if (mUploadMessage != null){ mUploadMessage.onReceiveValue(null); mUploadMessage = null; } }else { if(mUploadCallbackAboveL != null){ mUploadCallbackAboveL.onReceiveValue(null); mUploadCallbackAboveL = null; } } }
2.WebView 图片延迟加载:
有些页面如果包含网络图片,在移动设备上我们等待加载图片的时间可能会很长,所以我们需要让图片延时加载,这样不影响我们加载页面的速度,同样代码说话:
定义变量:
boolean blockLoadingNetworkImage=false;
在WebView初始化的时候设置,就是这么简单就可以了:
blockLoadingNetworkImage = true;webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器 return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); if (!blockLoadingNetworkImage){ webView.getSettings().setBlockNetworkImage(true); } } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); if (blockLoadingNetworkImage){ webView.getSettings().setBlockNetworkImage(false); } } });
3.JS调用native:
js调用原生大概有两种方法
1.截取url,获取指定的url,例如页面上有个拨打电话的调用,我们就可以在wenview中这样截取:
webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器 Log.e("zhaogl", url); if (url.startsWith("tel:")){//拨打电话 String[] ss = url.split(":"); if (ss.length > 1 && ss[1] != null){ CommonUtil.call(WebViewActivity.this,ss[1]); } }else if (url.equalsIgnoreCase("http://www.baidu.com/")){ WebViewActivity.this.finish(); }else { view.loadUrl(url); } return true; } });
2.调用Java写好的方法:
首先我们要定义一个方法给js调用,这里我把这个方法封装到一个类中:
public class InJavaScript { private static InJavaScript instance; public InJavaScript() { } public static InJavaScript getInstance() { if (instance == null){ instance = new InJavaScript(); } return instance; } /** * 分享 * @param str 内容 * @param targetUrl url */ @JavascriptInterface public void runOnAndroidShare(String str,String targetUrl) { WebViewEvent event = new WebViewEvent(); event.isShare = true; event.content = str; event.url = targetUrl; EventBus.getDefault().post(event); } /** * 关闭 window.close 不起作用,代替之 */ @JavascriptInterface public void closeWindowForAndroid(){ WebViewEvent event = new WebViewEvent(); event.isCloseWindow = true; EventBus.getDefault().post(event); }}
写好的java类及方法如果想让js调用,还需要有如下设置:
webView.addJavascriptInterface(InJavaScript.getInstance(), "injs");
js中就可以用以下方式调用:
function sendToAndroid(){ window.injs.runOnAndroidShare(str,str);//调用android的函数 }
注意,第二中方法在4.2以下版本存在js安全漏洞,但是目前市场上的安卓大部分都已经在4.2以上了,所以如果你的项目安全要求不是那么高,可以正常使用。现在有很多第三方的框架解决这个问题,大家可以去自己查找。
3.处理返回按键:
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) { if (photoSelectFragment != null){ photoSelectFragment.dismiss(); clearUploadCallBack(); } webView.goBack();// 返回前一个页面 return true; } return super.onKeyDown(keyCode, event); }
整理出来的源码
源码下载
更多相关文章
- android-PullToRefreshListView自动刷新问题
- Android(安卓)Device Chooser中显示Target unknown解决方法
- Android(安卓)onFragmentInteraction(Uri uri) 方法
- AppWidgetProvider
- 解决通过Intent调用系统拍照程序,返回图片太小的问题[android]
- Android(安卓)调用系统的分享功能
- 关于android中postDelayed方法的讲解
- 使用Android(安卓)studio 开发xposed插件
- Android(安卓)orm框架Sugar1.4源码(映射篇)