Android WebView 踩過的坑
阿新 • • 發佈:2019-01-09
首先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<Uri[]> mUploadCallbackAboveL;
private ValueCallback<Uri> mUploadMessage;
private class MyWebChromeClient extends WebChromeClient {
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
if (mUploadMessage != null) return;
mUploadMessage = uploadMsg;
showPhotoView();
}
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, "");
}
// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg, acceptType);
}
// For Android 5.0+
public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> 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);
}
整理出來的原始碼
原始碼下載