这篇文章主要讲小盆友在工作中遇到的一些问题,如果喜欢请给个心:
目录:
1、onReceivedSslError的应用
2、白名单拦截
3、登录、唤起原生支付
4、标题的优化
5、图片保存
1、onReceivedSslError的应用
在2017年11月11日双十一的冲击下,嵌套在app内的网页大多被劫持,公司的app的webview加载网页有白名单,一旦不是白名单中的网页就会不进行请求,导致会白屏。在这样的场景下,公司决定全部换成https的链接,换成了https,有些机型会有白屏问题,需要在WebViewClient的onReceivedSslError方法加入如下处理:
//为了避免https白屏
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
onReceivedSslError是在 SSL 证书验证错误时会进行回调,这里这样处理,其实是相当暴力,但却符合国内app的处理方式(尽量让用户少动脑少操作),话虽如此,这样的应用无法google play,因为google play有规定不能这样处理,也给出了如下的处理方式(其实就是将风险转给用户):
@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.notification_error_ssl_cert_invalid);
builder.setPositiveButton("continue", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
handler.proceed();
}
});
builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
handler.cancel();
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
2、白名单拦截
在上一小结讲到白名单,这里就略微提一下,操作很简单,在WebViewClient中重写shouldInterceptRequest方法
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
//isFilter是一个自定义绕白名单标记,在开启webview时,可以传入,如果为false,表示不拦截
if (!isFilter) {
return super.shouldInterceptRequest(view, url);
}
//isValidUrl方法可以自己定义,我的话是使用一个list存放(后台获取),判断url是否含有其中的字符串,
//若有,则说明在白名单中,进行正常请求;否则,返回空响应。
if (isValidUrl(url)) {
return super.shouldInterceptRequest(view, url);
}
return new WebResourceResponse("text/html", "UTF-8", myInputStream);
}
//空的响应
private InputStream myInputStream = new InputStream() {
@Override
public int read() throws IOException {
return -1;
}
};
3、登录、唤起原生支付
重写WebViewClient中的shouldOverrideUrlLoading
@Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
if (isLoginPage(url)) { //进行判断是否为登录链接(此处方法只是用于验证url是否为app规定的登陆页)
gotoRefreshToken(url); //进行刷新获取token(该方法只是发起获取token请求)
return true;
} else if (url.startsWith("weixin://wap/pay?")) { //微信
gotoPage(url, "请先安装微信APP,再进行支付");
return true;
} else if (url.startsWith("alipays://platformapi")) {//支付宝
gotoPage(url, null);
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
private void gotoPage(String url, String tip) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
startActivity(intent);
} else {
if (!TextUtils.isEmpty(tip)) {
ToastTool.showTips2Center(tip);
}
Log.e("webfragment", "route:未找到" + url);
}
}
4、标题的优化
当webview标题变动时,会调用WebChromeClient的onReceivedTitle,可以在方法中设置toolbar的标题,并需要手动在onProgressChanged中去判断是否加载完。
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
getWebCallback().setWebTitle(title);//此处回调改toolbar的标题
}
5、图片保存
需要长按一个图片弹出一个框提示“是否保存该图片”,webview并没有默认支持,需要自己做处理,只需要在给webview添加长按事件
mWebView.setOnLongClickListener(this);
然后在
@Override
public boolean onLongClick(View v) {
final WebView.HitTestResult result = ((WebView) v).getHitTestResult();
if (result != null) {
int type = result.getType();
//图片保存
if (type == WebView.HitTestResult.IMAGE_TYPE || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("提示");
builder.setMessage("是否保存该图片");
builder.setCancelable(false);
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String imgurl = result.getExtra(); //标签的内容
final String path = FileUtils.getMyCacheDir("aoyunWeb") + System
.currentTimeMillis() / 1000 + (imgurl
.endsWith(".png") ? ".png" : ".jpg");
final File file = new File(path); //生成文件
Observable<DownloadHelper.Progress> observable;
if (imgurl.startsWith("data:image/")) { //base64的图
} else { //网络图
}
}
});
builder.create().show();
return true;
}
}
}
6、webview唤起原生图片选择
在WebChromeClient中添加如下代码:
//安卓2.+使用
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg)");
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
getActivity().startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}
//安卓3.+使用
public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
Log.d(TAG, "openFileChoose( ValueCallback uploadMsg, String acceptType )");
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
getActivity().startActivityForResult(
Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE);
}
//安卓4.+使用
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
}
// Android 5.0+ 以上使用
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
mUploadCallbackAboveL = filePathCallback;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
return true;
}
在Activity中添加回调:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == WebFragment.FILECHOOSER_RESULTCODE) {
if (null == webFragment.mUploadMessage && null == webFragment.mUploadCallbackAboveL)
return;
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (webFragment.mUploadCallbackAboveL != null) {
onActivityResultAboveL(requestCode, resultCode, data);
} else if (webFragment.mUploadMessage != null) {
Uri uri = Uri.parse("file://" + uriToPath(this, result));
webFragment.mUploadMessage.onReceiveValue(uri);
webFragment.mUploadMessage = null;
}
}
}
并添加成员属性:
public ValueCallback<Uri> mUploadMessage;
public final static int FILECHOOSER_RESULTCODE = 1;
public ValueCallback<Uri[]> mUploadCallbackAboveL;
网友评论