Android WebView and JS Simple Interactive solution

Source: Internet
Author: User
<span id="Label3"></p><p><p>Recent research WebView and JS interaction, see a few open Source Library implementation, feel not satisfactory, The main problem is that the coupling is high, the use is not concise, and then reference the URI setting rules, pattern URI Similar protocol to customize a similar JS interactive protocol</p></p><p><p>More concise, custom protocol content styles such as: jsbridge://android-app/method123?a=123&b=345#jsmethod1 (p1,p2)</p></p><p><p>Protocol Description:</p></p><p><p>Scheme is defined as jsbridge, which is used to separate network requests (http) for the zone,<br>Authority defined as android-app, differentiating between different platform processing<br>Path is defined as calling the local method name method123<br>Query is defined as calling the local method parameter a=123&b=345<br>Fragment defined as the callback JS method #jsMethod1 (p1,p2)</p></p><p><p></p></p><p><p>This can be streamlined, flexible, good scalability, flexible use of the Characteristics. And then see the analytic implementation ·</p></p><pre class="brush:java;gutter:true;">public boolean Parsejsbridge (String url,webappinterface webnative) {//webappinterface is called as the Local method class instance if (!isprotocol (url) ) Return false; int i =-1; Uri uri = Uri.parse (url),//uri Resolution Protocol String methodName = Uri.getpath ();//call local method, method123 methodName = Metho Dname.replace ("/", ""); String params = uri.getquery ();//call Local method Parameter. a=123&b=345 String callback = uri.getfragment ();//parsing JS callback method, #jsMethod1 (p1,p2) i = Callback.lastindexof (' ( ‘); String Jsmethod = callback.substring (0,i); String jsparams = callback.substring (i+1,callback.length ()-1);//encapsulates The parsed result as jsresponse for subsequent use mjsres = new Jsresponse ( methodname,jsmethod); Mjsres.parsejscallbackparams (jsparams); Mjsres.parsenativeparams (params);<br>Here The local method is called by reflection string[] args = Mjsres.getmethodargs (); If (null==args) {//use reflection to call the parameterless method Jscallnoparammethod (webnative,methodname); }else{//call reflection has a parameter method int count = args.length; class[] Javaparamstype = new class[count]; For (int t=0;t<count;t++) {javaparamstype[t] = string.class; } Jscallparammethod (webnative,methodname,javaparamstype,mjsres.getmethodargs ()); } return true; }</pre><p><p></p></p><p><p>Protocol resolution complete Implementation class:</p></p><pre class="brush:java;gutter:true;">public class Jsprocessor {//private jsprocessor () {} private Jsresponse mjsres; Public jsresponse getjsresponse () {return mjsres; } public static Boolean Isprotocol (String Url) {return! Textutils.isempty (url) && Url.startswith ("jsbridge://"); }//jsbridge://android-app/method123?a=123&b=345#jsmethod1 (p1,p2) "public boolean Parsejsbridge (String Url,WebA Ppinterface webnative) {if (!isprotocol (url)) return false; int i =-1; Uri uri = Uri.parse (url); String methodName = Uri.getpath ();//method1 methodName = methodname.replace ("/", ""); string params = Uri.getquery ();//a=123&b=345 String callback = Uri.getfragment ();//#jsMethod1 (p1,p2) i = Callback.lastindexof (' ('); String Jsmethod = callback.substring (0,i); String jsparams = callback.substring (i+1,callback.length ()-1); Mjsres = new Jsresponse (methodname,jsmethod); Mjsres.parsejscallbackparams (jsparams); Mjsres.parsenativeparams (params); string[] args = Mjsres.getmethodargs (); If (null==args) {jscallnoparammethod (webnative,methodname); }else{int count = args.length; class[] Javaparamstype = new class[count]; For (int t=0;t<count;t++) {javaparamstype[t] = string.class; } Jscallparammethod (webnative,methodname,javaparamstype,mjsres.getmethodargs ()); } return true; public boolean Jscallnoparammethod (Object obj,string mname) {boolean success = false; Try {Method method=obj.getclass (). GetMethod (mname); Method.invoke (obj); Success = true; } catch (nosuchmethodexception E) {e.printstacktrace (); } catch (illegalaccessexception E) {e.printstacktrace (); } catch (invocationtargetexception E) {e.printstacktrace (); }catch (Exception Ex) {ex.prinTstacktrace (); } return success; }//getmethod ("sayHello", string.class,int.class); public boolean Jscallparammethod (Object obj,string mname,class<?>[] parametertypes,object[] Args) {if (paramet Ertypes.length!=args.length) return false; Boolean success = false; Try {method = Obj.getclass (). getmethod (mname,parametertypes); Method.invoke (obj, args); Success = true; } catch (nosuchmethodexception E) {e.printstacktrace (); } catch (illegalaccessexception E) {e.printstacktrace (); } catch (invocationtargetexception E) {e.printstacktrace (); }catch (Exception Ex) {ex.printstacktrace (); } return success; }}</pre><p><p></p></p><p><p>Jsresponse encapsulated entity class after parsing</p></p><pre class="brush:java;gutter:true;">public class Jsresponse {//call native public String methodName; Private map<string,string> nativeparams = new Hashmap<> (); Callback JS method public String calljsmethod;//public map<string,string> jsparams = new Hashmap<> (); private int jsparamcount; Public jsresponse (String javamethod,string JSMETHOD) {this.methodname = javamethod; This.calljsmethod = jsmethod; } public string[] Getmethodargs () {if (0==nativeparams.size ()) return null; string[] params = new String[nativeparams.size ()]; int n = 0; For (map.entry<string,string> entry:nativeParams.entrySet ()) {params[n] = Entry.getvalue (); n++; } return params; } public void Parsenativeparams (String params) {//int i = 0,len = Params.length (); If (!nativeparams.isempty ()) nativeparams.clear (); string[] eles = Params.split ("&"); For (String ele:eles) { int eq = Ele.indexof (' = '); String value = ele.substring (eq + 1); String name = ele.substring (0,eq); Nativeparams.put (name,value); }} public void Parsejscallbackparams (String jsparams) {string[] eles = Jsparams.split (","); Jsparamcount = eles.length; }}</pre><p><p></p></p><p><p>JS uses the rules protocol, triggering calls to the local method as follows, you can</p></p><pre class="brush:javascript;gutter:true;"><pre class="brush:javascript;gutter:true;">function Startrequest () { var iframe = document.createelement (' iframe '); Iframe.setattribute (' src ', ' jsbridge://android-app/showhello?a=hello-&b=i_from_js& #callbackHello (p1,p2) '); Document.body.appendChild (iframe); Iframe.parentNode.removeChild (iframe); iframe = null; }</pre></pre><p><p>Local Invoke JS callback method</p></p><pre class="brush:java;gutter:true;"><pre class="brush:java;gutter:true;"> void Executejscmd (String jscmd) { log.d (TAG, "pending execute JS command=" +jscmd); If (Build.VERSION.SDK_INT >= build.version_codes. KITKAT) { //async Execute mwebview.evaluatejavascript (jscmd, new valuecallback<string> () { @ Override public void Onreceivevalue (String value) { log.d (TAG, "async execute result=" +value); } ); }else {//this code was bad and would block the UI thread mwebview.loadurl (jscmd); } }</pre></pre><p><p></p></p><p><p>The following is the JS and local communication, through the Webviewclient shouldoverrideurlloading interception content judgment processing</p></p><pre class="brush:java;gutter:true;">Private class Monitorwebclient extends webviewclient {webappinterface webcallapp = new Webappinterface (activity); ... @Override public boolean shouldoverrideurlloading (WebView view, String url) {bool EAN handle = super.shouldoverrideurlloading (view, url); Jsprocessor Jspro = null; If (!handle) {jspro = new Jsprocessor (); handle = Jspro.parsejsbridge (url,webcallapp); } if (handle) {handlejscallback (jspro, "hello", "callback js method"); } return handle; } @Override public webresourceresponse shouldinterceptrequest (WebView view, webresourcerequest request) { If you need to pass files, intercept WebView resource requests, communicate the file as a stream//return new webresourceresponse ("image/jpeg", "UTF-8", new file InputStream (new File ("xxxx"); return super.shouldinterceptrequest (view, request); } }</pre><p><p></p></p><pre class="brush:java;gutter:true;"><pre class="brush:java;gutter:true;">void Handlejscallback (jsprocessor jspro,string ... Args) {<br>Javascript:showjavamessage (' javaresult ') "<br>Splicing js to execute the method name and parameter rules, such as the example String JsM = jspro.getjsresponse (). calljsmethod; If (! Textutils.isempty (jsM)) {// String jscmd = new StringBuilder (). append ("javascript:"). append (jsM).// append ( ' ('). append ("\ ' java\ '"). append (', '). append ("\ ' hello\ '"). append (') '). toString (); StringBuilder buf = new StringBuilder (). append ("javascript:"). append (jsM). append (' ('); If (args!=null && args.length>0) {// int pos = buf.length ()-1; For (String P:args) { buf.append (' \ '). append (p). append (' \ '). append (', '); } Buf.deletecharat (buf.length ()-1); } Buf.append (') '); Executejscmd (buf.tostring ()); } }</pre></pre><p><p></p></p><p><p> In addition to the above Shouldoverrideurlloading method interception processing, JS can also call the Alert,prompt method to pass the data, we need to rewrite webchromeclient by callback local method Onjsalert () , the Onjsprompt () method receives the corresponding function callback for data processing </p></p><pre class="brush:java;gutter:true;">Private class Appwebchromeclient extends webchromeclient {@Override public void Onreachedmaxappcachesize (lo ng spaceneeded, long totalusedquota, webstorage.quotaupdater quotaupdater) {quotaupdater.updatequota (spaceNeed Ed * 2); } @Override public boolean onconsolemessage (consolemessage cm) {log.d ("myapplication", Cm.messag E () + "--from line" + cm.linenumber () + "of" + Cm.sourceid ()); Return true; } @Override public boolean onjsprompt (WebView view, string url, string message, string defaultvalue, Jspromp TResult result) {if ("1001". equals (message)) {//parse parameter defaultvalue, call Java method and get result// Textexejs (); }//give JS return processing result result.confirm ("result"); Return false; } @Override public boolean Onjsalert (WebView view, string url, string message, jsresult Result) { LOG.D ("myapplication", url); Alertdialog alertdialog = new Alertdialog.builder (activity). Create (); Setting Dialog Title alertdialog.settitle ("JS come message"); Setting Dialog Message Alertdialog.setmessage (message); Alertdialog.show (); Return false; } }</pre><p><p></p></p><p><p><br></p></p><p><p></p></p><p><p>Calling the Local method class object</p></p><pre class="brush:java;gutter:true;"><pre class="brush:java;gutter:true;">public class Webappinterface { Context mcontext; /** instantiate the interface and set the context * /webappinterface (context c) { mcontext = c; } /** Show A toast from the Web page * /@JavascriptInterface public void Showtoast (String toast) { Toast.maketex T (mcontext, toast, toast.length_short). show (); @JavascriptInterface public void ShowDialog (String dialogmsg) { alertdialog alertdialog = new Alertdialog.builder (mcontext). Create (); Setting Dialog Title alertdialog.settitle ("JS triggered Dialog"); Setting Dialog Message alertdialog.setmessage (dialogmsg); Alertdialog.show (); } public void Showhello (String title,string msg) { toastutils.showlong (mcontext,title+msg);} }</pre></pre><p><p></p></p><p><p>JS Sample Content</p></p><pre class="brush:javascript;gutter:true;">

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.