How to use Android with HTML hybrid development

Source: Internet
Author: User
Tags setcookie
This time brings you how to use Android and HTML hybrid development, the use of Android and HTML mixed development of considerations, the following is the actual case, together to see.

Now a lot of apps will be nested HTML5 pages, such as frequent changes, and so on, some of the pages need native Java and HTML5 JS in the interactive operation, the following describes the use of Android HTML5:

1, about HTML5 kind of cookie

Web pages may use a lot of parameters such as user information, you can put this information in advance in the cookie, 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.S                         Etcookie (URL, value); }} cookiemanager.setcookie (URL, "client_id=" + constant.client_id + ";p ath=/;d OMA In=.                     Xxxx.com "); Cookiemanager.setcookie (URL, "appversion=" + Constant. VERSION + ";p ath=/;d omain=.              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; }

By adding a cookie before the Mwebview.loadurl (URL), the Web page can take the corresponding parameter value via a cookie.

2, about JS security issues

JS has a loophole before 4.2

With JavaScript, you can access everything on the current device's SD card, even contact information, text messages, and so on. Well, let's see how this is going to happen.

1,webview added a JavaScript object, and the current app has read-write SDcard permissions, namely: Android.permission.WRITE_EXTERNAL_STORAGE

2,js can traverse the Window object, find the object with the "GetClass" method, then get the runtime object through the reflection mechanism, then call the static method to execute some commands, such as the command to access the file.

3, you can get the information of the file name by getting the string from the input stream returned after executing the command. Then you can do whatever you want, it's dangerous. The core JS code is as follows:

function Execute (Cmdargs)    {for        (var obj. 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 more than 4.2 of the system

Over Android 4.2, Google has made a correction by declaring a @javascriptinterface on the Java remote method, as 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 ())");

Systems under 2,android 4.2

This problem is more difficult to solve, but it is not impossible to solve.

First, we definitely can't call the Addjavascriptinterface method again. On this issue, the most important thing is to know the JS event this action, JS and Java interaction We know, there are several, than prompt, alert and so on,

Such action will correspond to the corresponding method in the Webchromeclient class, for prompt, it corresponds to the method is 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 transfer the information (text) to Java, and Java can also transfer information (text) to JS, notify this idea can we find a solution?

After some attempts and analysis to find a more feasible solution, see the following small points:

"1" Let JS call a JavaScript method, this method is called prompt method, through the prompt to the information in JS, this information should be a meaningful text we combine, may contain: specific identity, method name, parameters and so on.

In the Onjsprompt method, we parse the passed text, get the method name, parameters, etc., and invoke the method of the Java object by invoking the specified method through the reflection mechanism.

"2" about the return value, you can return back through prompt, so that the 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, loading it through Loadurl, and registering it in an HTML page with the following code:

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]});}               ,}           ;}   }   ) ()

Description

1, jsinterface in the above code is the name of the object to register, it registered two methods, OnButtonClick (arg0) and Onimageclick (arg0, Arg1, arg2), if there is a return value, add the return.

2,prompt is our agreed string, which contains a specific identifier, MyApp:, followed by a string of JSON string containing the method name, parameters, object names, and so on.

3, when JS calls OnButtonClick or Onimageclick, it will callback to the Java layer Onjsprompt method, we then parse out the method name, parameters, object name, and then reflect the call method.

4,window.jsinterface This means that a JS object is declared on the window, declaring the method in the form: Method Name: Function (parameter 1, parameter 2)

3. Java and JS interaction in HTML5

1), Method one:

Mwebview.getsettings (). Setjavascriptenabled (True); Mwebview.addjavascriptinterface (this, "xxx");

Then implement the following methods in the current class:

@JavascriptInterface public void CallbackFromH5 (final String j) {//todo}

The name of the callbackFromH5 must be the same as the JS method name in the Web page

Java calls the JS method:

Mwebview.loadurl (String.Format ("javascript:java2js (0)");//This is the Java side call WebView JS

JS method name needs and the Web side has been

2) Method Two:

Jsbridge Method (Https://github.com/lzyzsd/JsBridge)

Android Jsbridge is an auxiliary tool for building communication (calling) bridges in native Java code and JavaScript code in Android apps

1 Introducing Jsbridge.jar into our engineering

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:o rientation= "Vertical" >            <!--button demo Java call Web--        <button             android:id= "@+id/button"           Android:layout_width= "Match_parent"           android:text= "@string/button_name"           android:layout_height= "DP"           />              <!--webview Demo Web call 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 Server Web page webview.loadurl ("https://www.baidu.com");            Must have the same name as JS function. Webview.registerhandler ("Submitfromweb", new Bridgehandler () {@Override public void Han                                  Dler (string data, Callbackfunction function) {string str = "HTML returned to Java data:" + "                      Maketext (Mainactivity.this, str, length_short). Show ();                   LOG.I (TAG, "handler = submitfromweb, data from web =" + data);               Function.oncallback (str + ", Java after processing:" + str.substring (,));           }              });           Impersonate the user to get 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, "webpage 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, "reponse 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 Listener Document.addeventlistener (' Webviewjavascriptbridgeready ', function (                  ) {callback (Webviewjavascriptbridge)}, False    ); Registers a callback function that invokes the initialization function when the first connection is Connectwebviewjavascriptbridge (bridge) {Bridge.init (function (message, RESP                  Onsecallback) {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//turn on DOM storage API function Mwebview.getsettings (). Setdomstorageenabled (True);                Open the 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 application Caches Cache directory Mwebview.getsettings (). Setappcachepath (Cachedirpath); Turn on the application Caches function Mwebview.GetSettings (). Setappcacheenabled (True); 

2, clear cache

/** * Clear WebView Cache */public void Clearwebviewcache () {//cleanup                     WebView Cache Database try {deletedatabase ("webview.db");               DeleteDatabase ("webviewcache.db");               } catch (Exception e) {e.printstacktrace (); }//webview cache files File Appcachedir = new file (Getfilesdir (). GetAbsolutePath () +ap               P_cacahe_dirname);                              LOG.E (TAG, "Appcachedir path=" +appcachedir.getabsolutepath ());               File Webviewcachedir = new file (Getcachedir (). GetAbsolutePath () + "/webviewcache");                              LOG.E (TAG, "Webviewcachedir path=" +webviewcachedir.getabsolutepath ());               Delete the WebView cache directory if (webviewcachedir.exists ()) {DeleteFile (webviewcachedir);         }//delete WebView Cache cache directory if (appcachedir.exists ()) {          DeleteFile (Appcachedir); }           }

3, in the use of WebView loading Web pages, there are some fixed resource files such as js/css/pictures and other resources will be relatively large, if directly from the network loading will cause the page to load relatively slow, and will consume more traffic. So these files should be in assets and packaged with the app.

This solves the problem by using the Shouldinterceptrequest (WebView view, String URL) function provided by API one (honeycomb) to load local resources.

API 21 also discards this method, overloading a new shouldinterceptrequest, replacing the URL with the request in the required parameters.

For example, there is a picture xxxxx.png, this image has been placed in the assets, now loaded with an external HTML, you need to directly put the assets inside the picture to load without needing to get back from the network. Of course, you can change the image link to file:///android_asset/xxxxx.png in HTML.

However, this HTML can not be in Android, Ios,wap in the public.

Webview.setwebviewclient (New Webviewclient () {@Override public webresourceresponse Shou                    Ldinterceptrequest (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 Webresourcer                           Esponse ("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 = n                   Ull                   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; }   }

Believe that you have read the case of this article you have mastered the method, more exciting please pay attention to the PHP Chinese network other related articles!

Recommended reading:

Code and order of writing in CSS real-combat project

CSS cascading mechanism using detailed

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.