Many APPs now have HTML5 pages embedded in them, such as those that change frequently. Some pages require native Java to interact with js in HTML5. Here is an introduction to the use of HTML5 in Android:
1. About HTML5 cookiesMany parameters such as user information may be used in web pages. You can put this information in cookies in advance. You can use the following methods:
public static void addCookies(Context context, WebView webView, String url) { String url=https://www.xxxx.com/xx/xx/ String protocol = ; String authority = ; try { URL urlObj = new URL(url) ; protocol = urlObj.getProtocol(); authority = urlObj.getAuthority(); } catch (Exception e) { e.printStackTrace(); } String ua = webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(Constant.PROJECT_NAME + / + ParamHandler.getVersion(context) + ( + ua + ; HFWSH)); if (!TextUtils.isEmpty(url) && !TextUtils.isEmpty(protocol) && !TextUtils.isEmpty(authority)) { if (protocol.equals(https) && authority.indexOf(liepin.com) > -1) { CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie (true); try { List<String> data = getCookiesString(); if (!ListUtils.isEmpty(data)) { for (String value : data) { cookieManager.setCookie(url, value); } } cookieManager.setCookie(url, client_id= + Constant.CLIENT_ID + ;path=/;domain=. XXXX.com); cookieManager.setCookie(url, appVersion= + Constant .VERSION + ;path=/;domain=.XXXX.com); CookieSyncManager.getInstance().sync(); } catch (Exception e) { LogUtils.e(Exception: + e.getMessage()); } } } }
public List<String> getCookiesString() { ArrayList data = new ArrayList(); this.clearExpired(); Collection values = this.mCookies.values(); Iterator var3 = values.iterator(); while(var3.hasNext() ) { SwiftCookie c = (SwiftCookie)var3.next(); data.add(c.toCookieString()); } return data; }
Add a cookie before mWebView.loadUrl(Url), and the web page can get the corresponding parameter value through the cookie.
2. Regarding the security issues of jsjs had vulnerabilities before 4.2
Through JavaScript, you can access anything on the current device's SD card, even contact information, text messages, etc. Okay, let's take a look at how this error occurred.
1. WebView adds a JavaScript object, and the current application has permission to read and write SDCard, that is: android.permission.WRITE_EXTERNAL_STORAGE
2. In JS, you can traverse the window object to find the object with the getClass method, then get the Runtime object through the reflection mechanism, and then call the static method to execute some commands, such as commands to access files.
3. Then get the string from the input stream returned after executing the command, and you can get the file name information. Then you can do whatever you want, it's so dangerous. The core JS code is as follows:
function execute(cmdArgs) { for (var obj in window) { if (getClass in window[obj]) { alert(obj); return window[obj].getClass().forName(java.lang.Runtime) .getMethod( getRuntime,null).invoke(null,null).exec(cmdArgs); } } }Solution: 1. Android 4.2 or above system
In Android 4.2 and above, Google has made a correction by declaring a @JavascriptInterface on the Java remote method, as shown in the following code:
class JsObject { @JavascriptInterface public String toString() { return injectedObject; } } webView.addJavascriptInterface(new JsObject(), injectedObject); webView.loadData(, text/html, null); webView.loadUrl(javascript:alert(injectedObject. toString()));2. Systems below Android 4.2
This problem is more difficult to solve, but it is not impossible.
First of all, we definitely can no longer call the addJavascriptInterface method. Regarding this issue, the most important thing is to know the action of JS event. We know that there are the following types of interaction between JS and Java, such as prompt, alert, etc.
Such actions will correspond to the corresponding methods in the WebChromeClient class. For prompt, its corresponding method is the onJsPrompt method. The declaration of this method is as follows:
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
Through this method, JS can pass information (text) to Java, and Java can also pass information (text) to JS. Can we find a solution to this idea?
After some trial and analysis, we found a more feasible solution. Please see the following points:
[1] Let JS call a Javascript method. In this method, the prompt method is called, and the information in JS is passed through prompt. This information should be a meaningful text that we combine, which may include: specific identifiers and method names. , parameters, etc.
In the onJsPrompt method, we parse the passed text to get the method name, parameters, etc., and then call the specified method through the reflection mechanism to call the method of the Java object.
[2] Regarding the return value, you can return it through prompt, so that the processing results of the method in Java can be returned to Js.
[3] We need to dynamically generate a JS script that declares the Javascript method, load it through loadUrl, and register it in the html page. The specific code is as follows:
javascript:(function JsAddJavascriptInterface_(){ if (typeof(window.jsInterface)!='undefined') { console.log('window.jsInterface_js_interface_name is exist!!');} else { window.jsInterface = { onButtonClick:function( arg0) { return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]})); }, onImageClick:function(arg0,arg1,arg2) { prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]})); }, }; } } )()
illustrate:
1. The jsInterface in the above code is the name of the object to be registered. It registers two methods, onButtonClick(arg0) and onImageClick(arg0, arg1, arg2). If there is a return value, add return.
2. The prompt is the string we agreed on, which contains the specific identifier MyApp:, followed by a string of JSON strings, which includes method names, parameters, object names, etc.
3. When JS calls onButtonClick or onImageClick, it will call back to the onJsPrompt method in the Java layer. We then parse out the method name, parameters, object name, and then call the method reflectively.
4. window.jsInterface means that a Js object is declared on the window. The form of the declared method is: method name: function (parameter 1, parameter 2)
3. Interaction between java and js in html51), Method 1:
mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(this, xxx);
Then implement the following method in the current class:
@JavascriptInterface public void callbackFromH5(final String j) { //TODO }
The name of callbackFromH5 must be the same as the js method name in the web page
Java calls js method:
mWebView.loadUrl(String.format(javascript:java2js(0)));//Here is the JS for calling webview on the java side
The js method name needs to be consistent with the web page
2) Method two:
jsbridge method (https://github.com/lzyzsd/JsBridge)
Android JsBridge is an auxiliary tool used to build a communication (call) bridge between the native java code and javascript code of the Android app.
1 Introduce jsBridge.jar into our project
Android Studio:
repositories { // ... maven { url https://jitpack.io } } dependencies { compile 'com.github.lzyzsd:jsbridge:1.0.4' }
2. Layout file
<?xml version=1.0 encoding=utf-8?> <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android android:layout_width=match_parent android:layout_height=match_parent android:orientation=vertical > <!-- button demonstrates Java calling web --> <Button android:id=@+id/button android:layout_width=match_parent android:text=@string/button_name android:layout_height=dp /> <!-- webview demonstrates web calling Java --> <com.github.lzyzsd.jsbridge.BridgeWebView android:id=@+id/ webView android:layout_width=match_parent android:layout_height=match_parent > </com.github.lzyzsd.jsbridge.BridgeWebView> </LinearLayout>
3. java code
//Load the server webpage webView.loadUrl(https://www.baidu.com); //Must have the same name as js function. webView.registerHandler(submitFromWeb, new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { String str =html data returned to java: + data; makeText(MainActivity.this, str, LENGTH_SHORT).show( ); Log.i(TAG, handler = submitFromWeb, data from web = + data); function.onCallBack( str + , after Java processing: + str.substring(,)); } }); //Simulate the user to obtain the local location User user = new User(); Location location = new Location(); location.address = xxx; user. location = location; user.name = Bruce; webView.callHandler(functionInJs, new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) { makeText(MainActivity.this, the web page is getting your information, LENGTH_SHORT).show(); } }); webView.send(hello);
webView.callHandler(functionInJs, data from Java, new CallBackFunction() { @Override public void onCallBack(String data) { // TODO Auto-generated method stub Log.i(TAG, response data from js + data); } }) ;
js call
var str1 = document.getElementById(text1).value; var str2 = document.getElementById(text2).value; //Call the local java method window.WebViewJavascriptBridge.callHandler( 'submitFromWeb' , {'param': str} , function( responseData) { document.getElementById(show).innerHTML = send get responseData from java, data = + responseData } ); //Register event listening document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); //Register the callback function and call the initialization function connectWebViewJavascriptBridge(function(bridge) { when connecting for the first time bridge.init(function(message, responseCallback) { console.log('JS got a message', message); var data = { 'Javascript Responds': 'Wee!' }; console.log('JS responding with', data); responseCallback(data); }); bridge.registerHandler(functionInJs, function(data, responseCallback) { document.getElementById(show). innerHTML = (data from Java: = + data); var responseData = Javascript Says Right back aka!; responseCallback(responseData); }); })
4. About the optimization of webView
1. Set WebView cache mode
private void initWebView() { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setRenderPriority(RenderPriority.HIGH); mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); //Set cache mode// Enable DOM storage API Function mWebView.getSettings().setDomStorageEnabled(true); //Enable database storage API function mWebView.getSettings().setDatabaseEnabled(true); String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; // String cacheDirPath = getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; Log.i(TAG, cacheDirPath=+cacheDirPath); //Set the database cache path mWebView.getSettings().setDatabasePath(cacheDirPath); //Set the Application Caches cache directory mWebView. getSettings().setAppCachePath(cacheDirPath); //Enable Application Caches function mWebView.getSettings().setAppCacheEnabled(true);
2. Clear cache
/** * Clear WebView cache*/ public void clearWebViewCache(){ //Clear Webview cache database try { deleteDatabase(webview.db); deleteDatabase(webviewCache.db); } catch (Exception e) { e.printStackTrace(); } //WebView cache file File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, appCacheDir path=+appCacheDir.getAbsolutePath()); File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+/webviewCache); Log.e(TAG, webviewCacheDir path=+webviewCacheDir.getAbsolutePath() ); //Delete webview Cache directory if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir); } //Delete webview cache directory if(appCacheDir.exists()){ deleteFile(appCacheDir); } }
3. When using WebView to load web pages, some fixed resource files such as js/css/images and other resources will be relatively large. If they are loaded directly from the network, the page will load slower and consume more traffic. So these files should be placed in assets and packaged with the app.
To solve this problem, use the shouldInterceptRequest(WebView view, String url) function provided by API 11 (HONEYCOMB) to load local resources.
API 21 deprecated this method again and overloaded a new shouldInterceptRequest. The required parameters replaced url with request.
For example, there is a picture xxxxx.png. This picture has been placed in assets. Now that an external HTML is loaded, the picture in assets needs to be directly taken out and loaded without re-obtaining it from the network. Of course, you can change the image link in html to file:///android_asset/xxxxx.png,
But this html cannot be shared in Android, ios, and WAP.
webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { WebResourceResponse response = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ response = super.shouldInterceptRequest(view ,url); if (url.contains(xxxxx.png)){ try { response = new WebResourceResponse(image/png,UTF-8,getAssets().open(xxxxx.png)); } catch (IOException e) { e.printStackTrace(); } } } // return super.shouldInterceptRequest(view , url); return response; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { WebResourceResponse response = null; response = super.shouldInterceptRequest(view, request); if (url.contains(xxxxx.png)){ try { response = new WebResourceResponse(image/png,UTF -,getAssets().open(xxxxx.png)); } catch (IOException e) { e.printStackTrace(); } } return response; } }
The above is the entire content of this article. I hope it will be helpful to everyone’s study. I also hope everyone will support VeVb Wulin Network.