最近接手一个需求,涉及到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(); } } } });