赞
踩
推荐:
如何设计一个优雅健壮的Android WebView?(上)
如何设计一个优雅健壮的Android WebView?(下)
Webview的WebSettings基本配置大概也就那么多,当然了也有其他的少用的配置,这个可以根据需求来定,具体的每一个配置属性有注释,其他的属性大家可以在网上都能查到。我所使用的如下:
public void setWebSettings(WebView mView){ WebSettings setting = mView.getSettings(); //支持Js setting.setJavaScriptEnabled(true); setting.setJavaScriptCanOpenWindowsAutomatically(true); //缓存模式 setting.setCacheMode(WebSettings.LOAD_DEFAULT); //支持内容重新布局 setting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //将图片调整到适合webview的大小 setting.setUseWideViewPort(true); setting.setLoadWithOverviewMode(true); //设置可以访问文件 setting.setAllowFileAccess(true); //支持自动加载图片 setting.setLoadsImagesAutomatically(true); try { setting.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } catch (NoSuchMethodError e) { e.printStackTrace(); } }
对于Webview中的两个Client(WebViewClient和WebChromeClient)的配置,这里我也不在简述,毕竟方法太多了,在接下来的书写中会有一部分的描述使用。
android.Manifest.permission.CAMERA)
android.Manifest.permission.READ_EXTERNAL_STORAGE
public class BaseWebChromeClient extends WebChromeClient { private final static int FILE_REQUEST_CODE_SNAPSHOT = 100; //拍照表单的结果回调 private final static int FILE_CHOOSER_RESULT_CODE = 101;// 相册表单的结果回调 private ValueCallback<Uri> mUploadMessage;// 5.0以下表单的数据信息 public ValueCallback<Uri[]> mUploadCallbackAboveL;//5.0以上表单的数据信息 private Uri imageUri; private Context mContext; public BaseWebChromeClient(Context context) { mContext = context; } @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { return super.onJsAlert(view, url, message, result); } @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); if (newProgress == 100) { ((BaseActivity) mContext).dismissLoadingDialog(); } } @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); //处理404错误 android 6.0 以下通过title获取 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { if (title.contains("404") || title.contains("500") || title.contains("Error")) { if (mContext instanceof BaseWebActivity) { ((BaseWebActivity) mContext).showErrorRefresh(view, mContext.getResources().getString(R.string.webview_not_found)); } } } } //<---------------------------------重要代码--------------------------------------------> @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { mUploadCallbackAboveL = filePathCallback; PictureBusiness.getInstance().setUploadCallbackAboveL(mUploadCallbackAboveL); String[] fileParams = fileChooserParams.getAcceptTypes(); if (fileParams.length > 0) { for (int i = 0; i < fileParams.length; i++) { LogUtil.i("BaseWebChromeClient", "FileChooserParams ----> " + fileParams[i]); } } if (fileParams[0].equals(PictureBusiness.IMAGE)) { PictureBusiness.getInstance().changePicture((Activity) mContext, PictureBusiness.IMAGE, false); } else if (fileParams[0].contains(PictureBusiness.VIDEO)) { PictureBusiness.getInstance().changePicture((Activity) mContext, PictureBusiness.VIDEO, false); } return true; } public void openFileChooser(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; } public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { mUploadMessage = uploadMsg; } public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { mUploadMessage = uploadMsg; } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK) { if (mUploadMessage != null) { mUploadMessage.onReceiveValue(null); } return; } //相册 & 拍照 if (requestCode == FILE_REQUEST_CODE_SNAPSHOT || requestCode == FILE_CHOOSER_RESULT_CODE) { if (null == mUploadMessage && null == mUploadCallbackAboveL) { return; } Uri result = data == null || (resultCode != RESULT_OK) ? null : data.getData(); if (mUploadCallbackAboveL != null) { onActivityResultAboveL(requestCode, resultCode, data); } else if (mUploadMessage != null) { /*if (result != null) { String path = getPath(mContext.getApplicationContext(), result); Uri uri = Uri.fromFile(new File(path)); mUploadMessage.onReceiveValue(uri); } else { mUploadMessage.onReceiveValue(imageUri); } mUploadMessage = null;*/ } } } @SuppressWarnings("null") @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) { if (mUploadCallbackAboveL == null) { return; } Uri[] results = null; switch (requestCode) { case FILE_CHOOSER_RESULT_CODE: if (resultCode == Activity.RESULT_OK) { if (data == null) { results = new Uri[]{imageUri}; } else { String dataString = data.getDataString(); ClipData clipData = data.getClipData(); if (clipData != null) { results = new Uri[clipData.getItemCount()]; for (int i = 0; i < clipData.getItemCount(); i++) { ClipData.Item item = clipData.getItemAt(i); results[i] = item.getUri(); } } if (dataString != null) { results = new Uri[]{Uri.parse(dataString)}; } } } break; case FILE_REQUEST_CODE_SNAPSHOT: if (resultCode == Activity.RESULT_OK) { String videoPath = null; File capture = PictureBusiness.getInstance().getSnapshot(); if (capture != null && capture.exists()) { videoPath = capture.getAbsolutePath(); } if (videoPath != null) { results = new Uri[]{Uri.parse("file://" + videoPath)}; } } break; default: break; } if (results != null) { mUploadCallbackAboveL.onReceiveValue(results); mUploadCallbackAboveL = null; } else { results = new Uri[]{imageUri}; mUploadCallbackAboveL.onReceiveValue(results); mUploadCallbackAboveL = null; } return; } }
3.代码中使用
①在onResume中做判断
if (mWebChromeClient.mUploadCallbackAboveL != null) {
mWebChromeClient.mUploadCallbackAboveL.onReceiveValue(null);
mWebChromeClient.mUploadCallbackAboveL = null;
}
②重写onActivityResult方法
mWebChromeClient.onActivityResult(requestCode, resultCode, data);
shouldOverrideUrlLoading :这个方法的返回值
return true 表示当前url即使是重定向url也不会再执行(除了在return true之前使用webview.loadUrl(url)除外,因为这个会重新加载)
return false 表示由系统执行url,直到不再执行此方法,即加载完重定向的ur(即具体的url,不再有重定向)
这个拦截方法其实也可以作为和H5的交互,比如在我自已的项目需求中,有一个按钮需要点击跳转,这个时候将返回设置为true,通过H5返回的数据(协商定义)进行判断跳转处理
获取Cookie使用的是CookieManager,这里我举例项目中使用Cookie,如下代码:
@Override protected void shouldUrlLoading(WebView view, String request) { if (request.contains("backpwd") || request.contains("regagreement") || request.contains("problem/a5.html")) { mBaseWeb.loadUrl(request); } else { //登录成功后,拦截操作 try { LogUtil.i("login", URLDecoder.decode(request, "utf-8")); if (URLDecoder.decode(request, "utf-8").contains(boLogin.getRedirect_url())) { //------使用代码 start------- CookieManager cookieManager = CookieManager.getInstance(); String cookieStr = cookieManager.getCookie(url); LoginCookie cookie = getLoginCookie(cookieStr); //------使用代码 end----- LoginBean loginBean = new LoginBean(); loginBean.setUid(cookie.getBfuid()); loginBean.setThirdUid(""); loginBean.setToken(cookie.getLoginToken()); loginBean.setuName(cookie.getBf_user_name()); loginBean.setLoginType(cookie.getLogin_type()); LoginBusiness.login(this, loginBean); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }
getLoginCookie方法如下:
/** * 解析Cookie * * @param cookieStr * @return */ protected LoginCookie getLoginCookie(String cookieStr) { HashMap<String, String> cookieContiner = new HashMap<>(); String[] keyvalues = cookieStr.split(";"); for (int i = 0; i < keyvalues.length; i++) { String[] keyPair = keyvalues[i].split("="); String cookieKey = keyPair[0].trim(); String cookieValue = keyPair.length > 1 ? keyPair[1].trim() : ""; cookieContiner.put(cookieKey, cookieValue); } String cookie = JSONObject.toJSONString(cookieContiner); LogUtil.i("cookie", "login cookie = " + cookieStr + "\n" + cookie); LoginCookie loginCookie = JSONObject.parseObject(cookie, LoginCookie.class); return loginCookie; }
以上只是举个例子,具体H5返回的Cookie需要由后端来定
关于Webview的注入我了解的有两种,也是最常用的,即H5调用Android的方式和Android调用H5的方式
webView.loadUrl("javascript:"+"方法名");
@SuppressLint("JavascriptInterface") class JSInterface { /** * Toast * * @param mToast 显示内容 */ @JavascriptInterface public void toast(String mToast) { SRLog.i(TAG, "--->toast " + mToast); Toast.makeText(WebActivity.this, mToast, Toast.LENGTH_SHORT).show(); } /** * 中间件 消息控制 * * @param str 内容 */ @JavascriptInterface public void startMiddleWare(String str) { SRLog.i(TAG, "--->middle " + str); TellManager.getInstance().sendAsr(getApplication(), getPackageName(), str); finish(); }
注意,WebSettings中的属性setJavaScriptEnabled(true);要设置为true
使用方式:
JSInterface mJsInterface = new JSInterface(this);
mBaseWeb.addJavascriptInterface(mJsInterface, "InjectOsUser");
//InjectOsUser这个是需要提供给H5调用的,如InjectOsUser.toast("xxx");
如何设计一个优雅健壮的Android WebView?(上)
如何设计一个优雅健壮的Android WebView?(下)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。