1、项目做了N个版本,整理一下用到的一些知识,Android与JS交互
由于Api最低是19,所以就不考虑17以前的方法了。下面是自己重写的webview,可以参考使用
public class SuperWebView extends WebView {
private Context context;
private WebViewCallback viewCallback;
private Gson gson = new Gson();
private boolean isNoFresh;
private int width;
private String specificUserId;
public SuperWebView(Context context) {
super(context);
initView(context);
}
public SuperWebView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
initAttr(context, attrs);
}
public SuperWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
initAttr(context, attrs);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
private void initAttr(Context context, AttributeSet attrs) {
}
private void initView(Context context) {
this.context = context;
width = AppUtils.getScreenDispaly(context)[0];
initErrorPage();
setVerticalScrollBarEnabled(false);
WebSettings webSettings = getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);// 设置允许访问文件数据
webSettings.setSupportZoom(false);
webSettings.setBuiltInZoomControls(true);
webSettings.setDomStorageEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setTextZoom(100);
webSettings.setUseWideViewPort(true);
webSettings.setSupportZoom(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webSettings.setMixedContentMode(webSettings.getMixedContentMode());
}
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setBlockNetworkImage(false);
setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return super.shouldOverrideUrlLoading(view, url);
}
@Override
public void onReceivedError(WebView webView, int i, String s, String s1) {
isError = true;
super.onReceivedError(webView, i, s, s1);
}
@Override
public void onReceivedHttpError(WebView webView, WebResourceRequest webResourceRequest, WebResourceResponse webResourceResponse) {
isError = true;
super.onReceivedHttpError(webView, webResourceRequest, webResourceResponse);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (viewCallback != null) {//回调方法
viewCallback.loadShow();
}
webUrl = url;
isFinish = false;
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
if (isError && !isFinish) {
mHandler.sendEmptyMessageDelayed(1, 0);
isFinish = true;
isError = false;
showErrorPage();
}
if (!isFinish) {
jsGetParams(jsParams);
hideErrorPage();
mHandler.sendEmptyMessageDelayed(1, 800);
isFinish = true;
}
super.onPageFinished(view, url);
}
});
//主要在此方法 将Android里面定义的类对象AndroidJs暴露给javascript
//new JavascriptInterface()用来管理交互代码 Androidports 约定标识 (可以自己定义)
addJavascriptInterface(new JavascriptInterface(), "Androidports");
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (width != 0) {
int mExpandSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
super.onMeasure(mExpandSpec, heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
private boolean isFinish = false;
private boolean isError = false;
public void setWebChromeClients(WebChromeClient webChromeClient) {
setWebChromeClient(webChromeClient);
}
public void setNoFresh(boolean b) {
isNoFresh = b;
}
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
if (viewCallback != null) {
viewCallback.loadHide();
}
} else if (msg.what == 2) {
if (titleCallback != null) {
titleCallback.titleChange((String) msg.obj);
}
}
}
};
/**
* 每次打开域名时都调下方法 jsGetParams 把参数传递过来
*/
private String jsParams = "";
private String webUrl = "";
public void setJsParams(Map<String, String> map) {
Map<String, String> map2 = publicParameters(map);
JSONObject json = new JSONObject(map2);
jsParams = json.toString();
}
public void jsGetParams(String s) {
String str = "javascript:jsGetParams(" + s + ")";
this.evaluateJavascript(str, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
String ss = s;
}
});
}
/**
* 发送信息 java 调用中的方法
*/
public void sendCommentsMsg(String info) {
String str = "javascript:jsSendMsg(" + info + ")";
this.evaluateJavascript(str, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
}
});
}
//同理 java 调用js方法 加载更多 jsAddMore次参数是js中的方法。
public void jsAddMore() {
this.evaluateJavascript("javascript:jsAddMore()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
}
});
}
private class JavascriptInterface extends Object {
private JavascriptInterface() {
}
//必须要用注解,否则不对
@android.webkit.JavascriptInterface
public void getContentWidth(String info) {
String ss = info;
}
//必须要用注解,否则不对
@android.webkit.JavascriptInterface
public void sendFirstLoadOver() {
VideoHighlightsActivity.isFirstLoadOver = true;
}
//必须要用注解,否则不对 in就是js传入的参数,一般是json对象,然后自己解析,根据类型做判断,做出相应操作
@android.webkit.JavascriptInterface
public void sendInfo(String info) {
if (!TextUtils.isEmpty(info)) {
Bean bean = gson.fromJson(info, Bean.class);
if (TextUtils.equals("MethodeType", bean.getType())) {
//自己操作
} else {
WebBean lBean = gson.fromJson(info, WebBean.class);
Intent intent = new Intent();
switch (lBean.getType()) {
case "OpenMain":
//跳转 最好自己先判断一下连击
intent.setClass(context, MainActivity.class);
intent.putExtra("WebBean", lBean);
context.startActivity(intent);
break;
default:
break;
}
}
}
}
}
//传入一些公共参数
public Map<String, String> publicParameters(Map<String, String> map) {
if (map == null) {
map = new HashMap<>();
}
map.put("uid", uid);
map.put("token", token);
map.put("appid", appId);
return map;
}
/**
* 显示自定义错误提示页面,用一个View覆盖在WebView
*/
private void showErrorPage() {
try {
RelativeLayout layout = (RelativeLayout) this.getParent();
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
if (mErrorView.getParent() != null) {
((RelativeLayout) mErrorView.getParent()).removeView(mErrorView);
}
layout.addView(mErrorView, layoutParams);
} catch (Exception e) {
}
}
private void hideErrorPage() {
try {
if (mErrorView.getParent() != null) {
((RelativeLayout) mErrorView.getParent()).removeView(mErrorView);
}
} catch (Exception e) {
}
}
/***
* 显示加载失败时自定义的网页
*/
private View mErrorView;
private void initErrorPage() {
if (mErrorView == null) {
mErrorView = View.inflate(context, R.layout.layout_load_error, null);
mErrorView.findViewById(R.id.load_web_error_tv).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!StringUtil.isEmpty(webUrl)) {
loadUrl(webUrl);
}
}
});
}
}
/**
* 设置web的回调方法
*
* @param callback
*/
public void setWebViewCallback(WebViewCallback callback) {
viewCallback = callback;
}
/**
* 回调接口
*/
public interface WebViewCallback {
void loadHide();
void loadShow();
}
/**
* 如果想要加入其它回调,请按照此方法添加即可
*
* @param callback
*/
public void setTitleCallback(TitleCallback callback) {
titleCallback = callback;
}
public interface TitleCallback {
void titleChange(String change);
}
}