原生webview使用的时候,会产生很多的问题,封装不彻底,以及ChromeClient的onShowFileChooser()方法和openFileChooser()方法的封装
WebViewClient通过html的input标签调用起android原生的应用,并且可以调用第三应用,如input的type=file标签调用摄像头,相册,摄像机,popwindow界面展示,各大手机浏览器都有的展示界面
// 3.0以下调用
public void openFileChooser(ValueCallback uploadMsg) {
openFileChooser(uploadMsg, "");
}
// android 3.0以上,android4.0以下:
public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
openFileChooser(uploadMsg, "", "");
}
// android 4.0 - android 4.3
public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
// 逻辑处理
Log.i("XWebChromeClient", "openFileChooser");
}
这三个方法是针对5.0一下的Android手机进行的方法,而onShowFileChooser()方法,是Android的chromeclient提供的原声方法,是在5.0以上的系统会调用这个方法
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
Log.i("XWebChromeClient", fileChooserParams.getAcceptTypes()[0]);
return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
}
因此针对这几个方法进行了封装。而通过不同的url传输针对不同的调用,可以采用webclient的封装,也就是对shouldOverrideUrlLoading()的方法进行逻辑处理
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url == null)
return false;
try {
if (url.startsWith("phone://")) {
//如果是打电话
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + url.substring(8, url.length())));
context.startActivity(intent);
return true;
} else if (url.startsWith("email://")) {
//发邮件
try {
Intent data = new Intent(Intent.ACTION_SENDTO);
data.setData(Uri.parse("mailto:" + url.substring(8, url.length())));
context.startActivity(data);
} catch (Exception e) {
if (e instanceof ActivityNotFoundException) {
Toast.makeText(context,"手机中没有安装邮件app",Toast.LENGTH_SHORT).show();
}
}
return true;
} else if (url.startsWith("local://")) {
// 发送定位
/*String substring = url.substring(8, url.length());
String[] array = substring.split(",");
String type = array[0];
String obj_id = array[1];
String count = array[2];
Intent intent = new Intent(context, MapDataActivity.class);
intent.putExtra("type", type);
intent.putExtra("obj_id", obj_id);
context.startActivity(intent);*/
return true;
} else if (url.startsWith("share://")) {
// 分享
String substring = url.substring(8, url.length());
String[] array = substring.split(",");
String type = array[0];
String obj_id = array[1];
// postData(type, obj_id);
return true;
} else if (url.startsWith("copy://")) {
//拷贝
String substring = url.substring(7, url.length());
ClipboardManager cmb = (ClipboardManager) context
.getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(substring);
Toast.makeText(context,"已复制到剪贴板",Toast.LENGTH_LONG).show();
return true;
} else if (url.startsWith("http:") || url.startsWith("https:")) {
// 正常的跳转
view.loadUrl(url);
return true;
} else {
//打开点击的第三方应用
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(intent);
return true;
}
} catch (Exception e) { //防止crash (如果手机上没有安装处理某个scheme开头的url的APP, 会导致crash)
return false;
}
}
最后对webview的生命周期进行封装。调用webview的生命周期方法
@Override
public void onResume() {
if (this.mWebView != null) {
if (Build.VERSION.SDK_INT >= 11){
this.mWebView.onResume();
}
this.mWebView.resumeTimers();
}
}
@Override
public void onPause() {
if (this.mWebView != null) {
if (Build.VERSION.SDK_INT >= 11){
this.mWebView.onPause();
}
this.mWebView.pauseTimers();
}
}
@Override
public void onDestroy() {
if(this.mWebView!=null){
this.mWebView.resumeTimers();
}
WebUtils.clearWebView(this.mWebView);
}
完整的demo在github.com/ci250454344/EWebView