操作前提
webview.getSettings().setJavaScriptEnabled(true);
通过webView调用JavaScript方法
webView.loadUrl("javascript:METHOD")
或者 webView.evaluateJavaScript("javascript:METHOD",CallBack)
//只能在4.4以上调用,效率高,能拿到返回结果
loadUrl在4.4之前的系统中会导致网页重载,4.4以后无影响
如果调用的方法有参数的话,javascript是弱类型,如果参数是字符串形式,则需要使用单引号’'进行包括,如果包含\之类的符号,则需要转义,使用\
JavaScript调用Java方法
webView.addJavaScriptInterface("接口对象","接口名字");
//这个名字给js端当做对象来调用内部方法
然后在接口对象类里面给所有JavaScript可以调用的Java方法添加@JavaScriptInterface
注解,加注解是防止h5进行攻击,因为没有注解的话,h5可以持有对象,可以调用对象的任何方法,私有的可以通过对象拿到Class进行反射调用
webview内存泄漏问题解决
在销毁过程中需保证 先执行webView的onDetachedFromWindow 然后执行destroy()释放webview
onDestroy()中
if (mWebView != null) {
ViewParent parent = mWebView.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(mWebView);
}
mWebView.removeAllViews();
mWebView.destroy(); //如果只写这一行代码,则不能保证onDetachedFromWindo会执行, 导致内存泄漏,因为这个方法内部判断了if(!isDestroyed){执行释放逻辑}
mWebView = null;
}
注:webview字体大小不随系统字体大小解决方法 webSettings.setTextZoom(100);
下面是基于JSBridge库的封装
public abstract class BaseWebView extends BridgeWebView {
public BaseWebView(Context context, AttributeSet attrs) {
super(context, attrs);
setWebAttr();
registerDefaultHandlers();
}
public BaseWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWebAttr();
registerDefaultHandlers();
}
public BaseWebView(Context context) {
super(context);
setWebAttr();
registerDefaultHandlers();
}
protected void setWebAttr() {
WebSettings settings = this.getSettings();
settings.setDomStorageEnabled(true);
setWebChromeClient(new WebChromeClient() {
@Override
public void onReceivedTitle(WebView view, String title) {
BaseWebView.this.onReceivedTitle(title);
super.onReceivedTitle(view, title);
}
@Override
public void onProgressChanged(WebView view, int newProgress) {
BaseWebView.this.onProgressChanged(newProgress);
super.onProgressChanged(view, newProgress);
}
});
}
protected abstract void registerDefaultHandlers();
protected abstract void onReceivedTitle(String title);
protected abstract void onProgressChanged(int progress);
}
public class DefaultWebView extends BaseWebView implements OpenNativePageHandler.Callback {
public interface Callback {
boolean openNativePage(JSONObject param);
void onReceivedError(WebView view);
void onReceivedTitle(String title);
void onProgressChanged(int progress);
}
public static abstract class SimpleCallBack implements Callback {
public void onReceivedError(WebView view) {
}
public void onReceivedTitle(String title) {
}
public void onProgressChanged(int progress) {
}
}
private static final String WEBVIEW_VERSION = "0";
private Callback mCallback;
public DefaultWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DefaultWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DefaultWebView(Context context) {
super(context);
}
public Callback getCallback() {
return mCallback;
}
public void setCallback(Callback callback) {
this.mCallback = callback;
}
@Override
protected void registerDefaultHandlers() {
//这些是提前注册好的handler,供h5在需要的时候调用
this.registerHandler("getInfo", new GetInfoHandler());
this.registerHandler("getLocation", new GetLocationHandler());
this.registerHandler("openNativePage", new OpenNativePageHandler(this));
}
@Override
protected void onReceivedTitle(String title) {
if (mCallback != null) {
mCallback.onReceivedTitle(title);
}
}
@Override
protected void onProgressChanged(int progress) {
if (mCallback != null) {
mCallback.onProgressChanged(progress);
}
}
public Map<String, String> getDefaultHeaders() {
Map<String, String> headers = new HashMap<>();
JSONObject utk = new JSONObject();
try {
User user = ServerHandler.getCurrentUser();
if (user != null) {
Integer userId = user.getUserId();
if (userId != null) {
utk.put("id", String.valueOf(userId));
}
String atk = user.getAtk();
if (atk != null) {
utk.put("atk", atk);
}
}
if (ColorVConst.DEVICE_ID != null) {
utk.put("udid", ColorVConst.DEVICE_ID);
}
utk.put("webview_ver", WEBVIEW_VERSION);
} catch (JSONException e) {
e.printStackTrace();
}
headers.put("utk", utk.toString());
return headers;
}
public void loadUrl(String url) {
super.loadUrl(url, getDefaultHeaders());
}
@Override
public boolean openNativePage(JSONObject param) {
if (mCallback != null) {
return mCallback.openNativePage(param);
}
return false;
}
@Override
public boolean showMoreBtn(int type, boolean showMore) {
if (mCallback != null) {
return mCallback.showMoreBtn(type, showMore);
}
return false;
}
@Override
protected BridgeWebViewClient generateBridgeWebViewClient() {
return new MyBridgeWebViewClient(this);
}
class MyBridgeWebViewClient extends BridgeWebViewClient {
public MyBridgeWebViewClient(BridgeWebView webView) {
super(webView);
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
if (mCallback != null) {
mCallback.onReceivedError(view);
}
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
if (mCallback != null) {
mCallback.onReceivedError(view);
}
}
@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
LogUtils.println("web view request url: " + request.getUrl());
LogUtils.println("web view request url: " + request.getMethod());
Map<String, String> headers = request.getRequestHeaders();
if (headers != null && headers.size() > 0) {
LogUtils.println("web view headers start-----------");
for (String key : headers.keySet()) {
String value = headers.get(key);
LogUtils.println("web view header " + key + ": " + value);
}
LogUtils.println("web view headers end-----------");
}
return super.shouldInterceptRequest(view, request);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
LogUtils.println("web view request url: " + url);
return super.shouldInterceptRequest(view, url);
}
}
}
public abstract class BaseHandler implements BridgeHandler {
private static final String DEFAULT_ERROR_MESSAGE="出错了";
private static final String ERROR_MESSAGE_KEY = "error_message";
private static final String ERROR_CODE_KEY = "error_code";
protected void handlerError(String errorMsg,int errorCode, CallBackFunction function)
{
JSONObject jsonObject = new JSONObject();
try {
if (errorMsg != null) {
jsonObject.put(ERROR_MESSAGE_KEY, errorMsg);
}
else {
jsonObject.put(ERROR_MESSAGE_KEY,DEFAULT_ERROR_MESSAGE);
}
jsonObject.put(ERROR_CODE_KEY,errorCode);
} catch (JSONException e) {
e.printStackTrace();
}
if (function != null) {
function.onCallBack(jsonObject.toString());
}
}
protected void handlerError(String errorMsg,CallBackFunction function)
{
this.handlerError(errorMsg,0,function);
}
protected void handlerError(CallBackFunction function)
{
this.handlerError(null,0,function);
}
}
public class GetInfoHandler extends BaseHandler {
@Override
public void handler(String data, CallBackFunction function) {
JSONObject info = new JSONObject();
try {
//塞入数据
} catch (Exception e) {
e.printStackTrace();
this.handlerError(e.getLocalizedMessage(),function);
return;
}
function.onCallBack(info.toString());
}
}