背景
android原生与Html5混合开发现在依然是开发公司选择的开发方式,本篇文章主要给大家分享的知识点主要有以下几点:
1.拦截Html5 js window.open(url)方法:
(1)WebView基本属性:
webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
webSetting.setJavaScriptEnabled(true);
webSetting.setAllowFileAccess(true);
webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSetting.setSupportZoom(true);
webSetting.setBuiltInZoomControls(true);
webSetting.setUseWideViewPort(true);
webSetting.setSupportMultipleWindows(true);
webSetting.setAppCacheEnabled(true);
webSetting.setDomStorageEnabled(true);
webSetting.setGeolocationEnabled(true);
webSetting.setDatabaseEnabled(true);
// 缓存白屏
String appCachePath = getApplicationContext().getCacheDir()
.getAbsolutePath() + "/webcache";
// 设置 Application Caches 缓存目录
webSetting.setAppCachePath(appCachePath);
webSetting.setDatabasePath(appCachePath);
webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);
(2)设置webView.loadUrl(url),并拦截js重定向方法 讲解: ** if (hitTestResult.getType() == WebView.HitTestResult.UNKNOWN_TYPE)** 判断js是否为重定向方法,如果是就直接拦截 return false
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//这里可以对特殊scheme进行拦截处理
//判断重定向的方式一
WebView.HitTestResult hitTestResult = view.getHitTestResult();
if (hitTestResult == null) {
clearHistory();
return false;
}
//重定向不再跳转
if (hitTestResult.getType() == WebView.HitTestResult.UNKNOWN_TYPE) {
clearHistory();
return false;
}
return false;
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return super.shouldOverrideUrlLoading(view, request);
}
});
webView.setWebChromeClient(myWebChromeClient);
webView.loadUrl(url);
}
// 注:webview.loadUrl(url);必须在 webView.setWebChromeClient(myWebChromeClient);
后面执行,否则无法实现拦截。
(3).实例化WebChromeClient myWebChromeClient方法
private WebChromeClient myWebChromeClient = new WebChromeClient() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
mUploadCallbackForHighApi = filePathCallback;
Intent intent = fileChooserParams.createIntent();
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
// startActivityForResult(photoPickerIntent, PICTURE_REQUEST_CODE);
// intent.addCategory(Intent.CATEGORY_OPENABLE);
// if (intent.getType().contains("image")) {
// intent.setType("image/*");
// }
try {
startActivityForResult(photoPickerIntent, REQUEST_CODE_FILE_CHOOSER);
} catch (ActivityNotFoundException e) {
mUploadCallbackForHighApi = null;
return false;
}
return true;
}
private void openFilerChooser(ValueCallback<Uri> uploadMsg) {
mUploadCallbackForLowApi = uploadMsg;
startActivityForResult(Intent.createChooser(getFilerChooserIntent(), "File Chooser"), REQUEST_CODE_FILE_CHOOSER);
}
// For 3.0+
protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
openFilerChooser(uploadMsg);
}
//For Android 4.1+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFilerChooser(uploadMsg);
}
@Override
public void onProgressChanged(WebView webView, int i) {
if (i == 100) {
progressBar.setVisibility(8);
progressBar.setProgress(0);
} else {
progressBar.setVisibility(0);
progressBar.setProgress(i);
}
}
@Override
public boolean onCreateWindow(WebView webView, boolean b, boolean b1, Message message) {
WebView webView1 = new WebView(MainActivity.this);
webView1.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri contentUrl = Uri.parse(url);
intent.setData(contentUrl);
startActivity(intent);
// web.loadUrl(url);//将拦截到url交由第一个WebView打开
return true;
}
});
WebView.WebViewTransport transport = (WebView.WebViewTransport) message.obj;
//以下的操作应该就是让新的webview去加载对应的url等操作。
transport.setWebView(webView1);
message.sendToTarget();
return true;
}
};
(4)拦截js window.open(url)
我们都知道js执行window.open(url)是打开一个新窗口来加载Html,但是在Android WebView 并不支持打开新窗口,所以需要我们重写onCreateWindow()方法,它的主要作用就是跟window.open(url)方法一样,都是新建一个窗口。其核心代码:
@Override
public boolean onCreateWindow(WebView webView, boolean b, boolean b1, Message message) {
WebView webView1 = new WebView(MainActivity.this);
webView1.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri contentUrl = Uri.parse(url);
intent.setData(contentUrl);
startActivity(intent);
// web.loadUrl(url);//将拦截到url交由第一个WebView打开
return true;
}
});
WebView.WebViewTransport transport = (WebView.WebViewTransport) message.obj;
//以下的操作应该就是让新的webview去加载对应的url等操作。
transport.setWebView(webView1);
message.sendToTarget();
return true;
}
(5)js 选择图片调用原生相机需重写 onShowFileChooser()方法,其中根据android 系统版本的不同调用不同的方法,其核心代码如下:
** * 5.0以上调用**
private ValueCallback<Uri> mUploadCallbackForLowApi;
private ValueCallback<Uri[]> mUploadCallbackForHighApi;
private static final int REQUEST_CODE_FILE_CHOOSER = 1;
public static final int P_REQUEST_CODE = 100;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
mUploadCallbackForHighApi = filePathCallback;
Intent intent = fileChooserParams.createIntent();
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
// startActivityForResult(photoPickerIntent, PICTURE_REQUEST_CODE);
// intent.addCategory(Intent.CATEGORY_OPENABLE);
// if (intent.getType().contains("image")) {
// intent.setType("image/*");
// }
try {
startActivityForResult(photoPickerIntent, REQUEST_CODE_FILE_CHOOSER);
} catch (ActivityNotFoundException e) {
mUploadCallbackForHighApi = null;
return false;
}
return true;
}
4.0、3.0以上调用
private void openFilerChooser(ValueCallback<Uri> uploadMsg) {
mUploadCallbackForLowApi = uploadMsg;
startActivityForResult(Intent.createChooser(getFilerChooserIntent(), "File Chooser"), REQUEST_CODE_FILE_CHOOSER);
}
// For 3.0+
protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
openFilerChooser(uploadMsg);
}
//For Android 4.1+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFilerChooser(uploadMsg);
}
(6)openFilerChooser 选择文件方法:
private void openFilerChooser(ValueCallback<Uri> uploadMsg) {
mUploadCallbackForLowApi = uploadMsg;
startActivityForResult(Intent.createChooser(getFilerChooserIntent(), "File Chooser"), REQUEST_CODE_FILE_CHOOSER);
}
(7)getFilerChooserIntent() 方法:
private Intent getFilerChooserIntent() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
if (intent.getType().contains("image")) {
intent.setType("image/*");
}
return intent;
}
(8)重写 onActivityResult() 回调方法,将选中后的文件回传给网页js
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_FILE_CHOOSER && (resultCode == RESULT_OK || resultCode == RESULT_CANCELED)) {
afterFileChooseGoing(resultCode, data);
}
(9)afterFileChooseGoing()方法将根据系统版本不同会传给网页js处理
private void afterFileChooseGoing(int resultCode, Intent data) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mUploadCallbackForHighApi == null) {
return;
}
mUploadCallbackForHighApi.onReceiveValue(WebChromeClient.
FileChooserParams.parseResult(resultCode, data));
mUploadCallbackForHighApi = null;
} else {
if (mUploadCallbackForLowApi == null) {
return;
}
Uri result = data == null ? null : data.getData();
mUploadCallbackForLowApi.onReceiveValue(result);
mUploadCallbackForLowApi = null;
}
}
说明:感谢其他作者提供思路,本篇博客仅作为记录知识使用.