最近接手一个需求,涉及到h5页面调用java方法。
虽然开发Android三年了,但我并没有开发过需要h5页面调用java方法的需求。在做相关的业务开发之前,我自己研究了一些js调用java代码的背景知识,这里做一下总结。
WebView基本使用方法:
(1)可动态添加、也可在xml内添加
xml中添加
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
动态添加
webViewContainer = (LinearLayout) mRootView.findViewById(R.id.h5_webview_container);
webViewContainer.removeAllViews();
webView = new H5WebView(context);
webView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
//初始化
webViewContainer.addView(webView);
(2)设置WebView相关属性
private void initWebViewSetting() {
WebSettings webSetting = this.getSettings();
if(VERSION.SDK_INT >= 16) {
webSetting.setAllowFileAccessFromFileURLs(true);
webSetting.setAllowUniversalAccessFromFileURLs(true);
}
if(Env.isTestEnv() && VERSION.SDK_INT > 19) {
setWebContentsDebuggingEnabled(true);
}
if(VERSION.SDK_INT >= 21) {
webSetting.setMixedContentMode(0);
}
if(VERSION.SDK_INT >= 17) {
webSetting.setMediaPlaybackRequiresUserGesture(false);
}
this.setVerticalScrollBarEnabled(false);
this.setHorizontalScrollBarEnabled(false);
this.setOverScrollMode(2);
String padFlag = "";
if(DeviceInfoUtil.isTablet()) {
padFlag = "_Ctrip_Pad_App_";
}
String dbPath;
if(StringUtil.emptyOrNull(H5Global.USER_AGENT_STRING) || !H5Global.USER_AGENT_STRING.contains("CtripWireless_")) {
dbPath = webSetting.getUserAgentString() + "_eb64_" + padFlag + this.getCustomAppName() + "CtripWireless_" + H5UtilPlugin.getAppVersion(this.getContext());
H5Global.USER_AGENT_STRING = dbPath;
}
webSetting.setUserAgentString(H5Global.USER_AGENT_STRING);
if(VERSION.SDK_INT >= 11) {
webSetting.setAllowContentAccess(true);
}
webSetting.setJavaScriptEnabled(true);
webSetting.setDomStorageEnabled(true);
dbPath = this.getContext().getApplicationContext().getDir("database", 0).getPath();
webSetting.setDatabasePath(dbPath);
webSetting.setUseWideViewPort(true);
webSetting.setLoadWithOverviewMode(true);
webSetting.setAppCacheEnabled(true);
webSetting.setAppCacheMaxSize(10506250L);
webSetting.setAppCachePath(dbPath);
webSetting.setTextSize(TextSize.NORMAL);
webSetting.setRenderPriority(RenderPriority.HIGH);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
this.setWebChromeClient(new VideoEnabledWebChromeClient() {
{
Object var3 = null;
if(EncodeUtil.classVerify) {
System.out.println(ClassLoadVerifyPatch.class);
}
}
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
String message = consoleMessage.message();
int lineNumber = consoleMessage.lineNumber();
String sourceID = consoleMessage.sourceId();
String log = "日志:" + message;
H5WebView.this.writeLog(log);
H5WebView.this.printLogInfo(log);
return super.onConsoleMessage(consoleMessage);
}
});
this.setWebViewClient(this.getWebClient());
}
Android如何为h5提供一个可调用方法:
(1)在WebView中添加javaScript可以直接调用的接口:
addJavascriptInterface()
这个接口有两个参数,第一个参数就是
包含了JS代码需要调用的java方法的类的实例,第二个参数是
给这个实例起一个名字。
(2)在JS中调用java方法的代码:
Test.doSomething();
这个“Test”就是我们在上一步给实例起的名字,doSomething方法是我们写好的给js调用的方法。
(3)注意事项
在doSomething方法里的代码是要运行在主线程上的,所以要记得加上runOnUiThread。
Android如何注入js文件:
1、为什么需要注入js文件?
因为在我们开发的一个app上,h5的埋点上报方法总是出错,所以希望h5的埋点上报通过调用Android的埋点上报方法来实现。关键在于,h5方面已经无法在原本的js上直接修改了,需要加入一个js文件来hook到h5的埋点上报方法,然后再调用android的原生方法。
这就需要在Android加载完每个h5页面时注入一个js文件,并且Android需要为h5提供一个埋点上报方法。
2、如何实现注入.js文件?
我们在这个app上使用的是目前使用最广泛的webViewJavaScriptBridge开源库,这个开源库提供了webView加载完成的回调方法。我们只需要在这里注入.js文件?
try {
InputStream is = webView.getContext().getAssets()
.open("CtripLocalUBT.js");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String js = new String(buffer);
executeJavascript(js);
} catch (IOException e) {
e.printStackTrace();
}
3、如何为h5提供可调用的Android方法?
registerHandler("trackJSLog", new WVJBHandler() {
@Override
public void request(Object data, WVJBResponseCallback callback) {
Log.e(TAG, "track_js_callback");
String d = (String) data;
if (!TextUtils.isEmpty(d)) {
try {
JSONObject object = new JSONObject(d);
String code = object.optString("code");
JSONObject tags = object.optJSONObject("tags");
HashMap<String, String> map = JsonHelper.JSONObjectToHashMap(tags);
CtripActionLogUtil.trackJSLog(code, map);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});