import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.webkit.*;
import android.widget.EditText;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import java.io.Serializable;
import java.util.Locale;
/**
* Created by hp on 2017/8/31.
* 通用WebView
*/
public class CommonWebView extends WebView implements Serializable {
private static String tag = "CommonWebView";
private static boolean DEBUG = false;
public CommonWebView(Context context) {
this(context, null);
}
public CommonWebView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CommonWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// Generic
setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
setVerticalScrollBarEnabled(false);
setHorizontalScrollBarEnabled(false);
// WebSettings
WebSettings settings = this.getSettings();
settings.setDefaultTextEncodingName("utf-8");
settings.setJavaScriptEnabled(true);//支持js
settings.setDomStorageEnabled(true);
settings.setLoadsImagesAutomatically(true);
setWebViewClient(new DefaultWebViewClient(getContext()));
setWebChromeClient(new DefaultWebChromeClient());
}
@Override
public WebSettings getSettings() {
return super.getSettings();
}
/**
* @param object 供JS调用的实例
* @param name 内部写定为 {@code "android"}
*/
@SuppressLint("JavascriptInterface")
@Override
public void addJavascriptInterface(Object object, String name) {
super.addJavascriptInterface(object, name);
}
public void registerJSO(Object object) {
addJavascriptInterface(object, "android");
}
@Override
public void loadUrl(String url) {
super.loadUrl(url);
System.out.println("loadUrl=" + url);
}
@Override
public void goBack() {
if (canGoBack()) {
super.goBack();
}
}
@Override
public void goForward() {
if (canGoForward()) {
super.goForward();
}
}
@Override
public void goBackOrForward(int steps) {
super.goBackOrForward(steps);
}
public void setDebug(boolean isDebug) {
DEBUG = isDebug;
}
public static class DefaultWebViewClient extends WebViewClient {
private Context context;
public DefaultWebViewClient(@NonNull Context context) {
this.context = context;
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
// New API
// 拦截'tel:'链接
String targetUrl = request.getUrl().getScheme();
if (matchSchemes(targetUrl) && context != null) {
Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
context.startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, request);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String targetUrl) {
// Old API
// 拦截'tel:'链接
if (matchSchemes(targetUrl) && context != null) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(targetUrl));
context.startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, targetUrl);
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
String msg = "onReceivedError api-old";
msg += String.format(
Locale.CHINESE,
": (%d) %s, %s",
errorCode,
failingUrl,
description
);
if (DEBUG) Log.e(tag, msg);
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
String msg = "onReceivedError api-new";
if (Build.VERSION.SDK_INT >= 23) {
msg += String.format(
Locale.CHINESE,
": (%d) %s, %s",
error.getErrorCode(),
request.getUrl().toString(),
error.getDescription()
);
}
if (DEBUG) Log.e(tag, msg);
}
@Override
public void onReceivedHttpAuthRequest(final WebView view, final HttpAuthHandler handler, final String host, final String realm) {
LinearLayout linearView = new LinearLayout(this.context);
linearView.setOrientation(LinearLayout.VERTICAL);
final EditText nameEdit = new EditText(this.context);
nameEdit.setHint("用户名");
linearView.addView(nameEdit);
final EditText passEdit = new EditText(this.context);
passEdit.setHint("密码");
linearView.addView(passEdit);
new AlertDialog.Builder(this.context).setTitle(host)
.setMessage(realm)
.setView(linearView)
.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
handler.proceed(nameEdit.getText().toString().trim(), passEdit.getText().toString().trim());
}
})
.setPositiveButton("", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
handler.cancel();
}
})
.create()
.show();
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
}
public static class DefaultWebChromeClient extends WebChromeClient {
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
if (DEBUG) {
System.out.println(String.format(Locale.CHINESE, "%s---> [%s:Line(%d)] %s", tag, consoleMessage.messageLevel(), consoleMessage.lineNumber(), consoleMessage.message()));
}
return super.onConsoleMessage(consoleMessage);
}
}
/**
* 匹配链接协议,并匹配冒号间是否带空格
*
tel:
*
tel :
*/
private static boolean matchSchemes(String url) {
return url != null && (
url.startsWith("mailto:")
|| url.startsWith("mailto :")
|| url.startsWith("tel:")
|| url.startsWith("tel :")
);
}
}