package com.v7lin.android.env.webkit;
import java.util.concurrent.atomic.AtomicBoolean;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
/**
* 辅助处理各类通知、请求等事件
*
* 错误页面时,调用系统错误页面时:
*
* 有的机器(Sony LT28h,4.0.4)会回调 onReceivedError 之后,又立即回调 onPageStarted,执行两次 onPageStarted 和两次 onPageFinished
*
* 有的机器(三星 S5830,2.3.5)第一次错误页面执行一次 onPageStarted 和两次 onPageFinished,随后是一次 onPageStarted 和一次 onPageFinished
*
* 有的机器(三星 I9500,4.4.2)则不会
*
* @author v7lin E-mail:v7lin@qq.com
*/
public class CompatWebViewClient extends WebViewClient {
private static final String JAVASCRIPT_404 = "javascript:" +
//
//"document.body.style.color='#000000';" +
//
"document.body.innerHTML=\"\"";
private WebApiClient mWebApiClient;
private ClientManager mClientManager;
public CompatWebViewClient(Context context, WebApiClient client) {
super();
this.mWebApiClient = client;
setup();
}
private void setup() {
mClientManager = new ClientManager();
}
/**
* 控制更新返回键
*/
@Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
super.doUpdateVisitedHistory(view, url, isReload);
if (mWebApiClient != null) {
mWebApiClient.doUpdateVisitedHistory(view, url, isReload);
}
}
/**
* 控制加载新 URL
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
boolean shouldOverride = mWebApiClient != null && mWebApiClient.shouldOverrideUrlLoading(view, url);
if (!shouldOverride) {
shouldOverride = true;
view.loadUrl(url);
}
return shouldOverride || super.shouldOverrideUrlLoading(view, url);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
mClientManager.markStarted(mWebApiClient, view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mClientManager.markFinished(mWebApiClient, view, url);
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
mClientManager.markError(mWebApiClient, view, errorCode, description, failingUrl);
}
static class ClientManager {
private final Js404Manager mJs404Manager = new Js404Manager();
private boolean mIsErrorCall = false;
private boolean mIsRightFinish = true;
public ClientManager() {
super();
}
public void markError(WebApiClient client, WebView view, int errorCode, String description, String failingUrl) {
mIsErrorCall = true;
if (client != null) {
client.onReceivedError(view, errorCode, description, failingUrl);
}
mJs404Manager.markError(view);
}
public void markStarted(WebApiClient client, WebView view, String url, Bitmap favicon) {
if (!mIsErrorCall) {
mJs404Manager.reset();
if (client != null) {
client.onPageStarted(view, url, favicon);
}
} else {
mIsRightFinish = false;
}
}
public void markFinished(WebApiClient client, WebView view, String url) {
if (mIsRightFinish) {
if (client != null) {
client.onPageFinished(view, url);
}
}
mJs404Manager.markFinished(view);
mIsErrorCall = false;
mIsRightFinish = true;
}
}
static class Js404Manager {
private final AtomicBoolean markError = new AtomicBoolean(false);
public Js404Manager() {
super();
}
public void reset() {
markError.set(false);
}
public void markError(WebView view) {
markError.compareAndSet(false, true);
new Js404Action(view).exec();// 避免系统错误页面闪烁
}
public void markFinished(WebView view) {
if (markError.compareAndSet(true, false)) {
new Js404Action(view).exec();// 避免JS错误页面被取缔
}
}
}
static class Js404Action implements Runnable {
private WebView view;
public Js404Action(WebView view) {
super();
this.view = view;
}
public void exec() {
view.post(this);
}
@Override
public void run() {
// 用javascript隐藏系统定义的404页面信息
view.loadUrl(JAVASCRIPT_404);
}
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
// super.onReceivedSslError(view, handler, error);
// 忽略证书的错误继续Load页面内容
handler.proceed();// 默认 handler.cancel();
}
}