The art of Building Bridges for Android Hybrid Apps

14
The Art of Building Bridges Android WebView Bridge in Depth Bartłomiej Pisulak

Transcript of The art of Building Bridges for Android Hybrid Apps

Page 1: The art of Building Bridges for Android Hybrid Apps

The  Art  of  Building  Bridges

Android  WebView  Bridge  in  Depth

Bartłomiej  Pisulak

Page 2: The art of Building Bridges for Android Hybrid Apps

Three  types  of  Mobile  Apps

Page 3: The art of Building Bridges for Android Hybrid Apps

Market  Share

According  to  Gartner  more  than  50%  of  mobile  apps  deployed  will  be  hybrid

Page 4: The art of Building Bridges for Android Hybrid Apps

ArchitectureIt’s  all  about  WebView…

So  what’s  the  difference?

Page 5: The art of Building Bridges for Android Hybrid Apps

The  Bridge

Bridge  between  Native  and  JS

JS  -­‐>  Native  Native  -­‐>  JS

Page 6: The art of Building Bridges for Android Hybrid Apps

JS_ObjectJavaScript  -­‐>  Java

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.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } }

Let’s  build  an  interface:

Page 7: The art of Building Bridges for Android Hybrid Apps

JS_ObjectJavaScript  -­‐>  Java

JS WebView

Quite  good  performance  Use  native  bridging  suggested  by  Google  

Error  prone

<script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>

WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true);

webView.addJavascriptInterface(new WebAppInterface(this), "Android");

Page 8: The art of Building Bridges for Android Hybrid Apps

Prompt JavaScript  -­‐>  Java

JS WebChromeClient

Doesn’t  crash  the  emulator  It’s  very  slow  

Overrides  default  prompt  behaviour  in  WebView  Criticised  as  antipattern

<script type="text/javascript"> prompt("toast", "This is Toast message"); </script> @Override

public boolean onJsPrompt (WebView view, String url, String message, String defaultValue, JsPromptResult result) { // message determines action if(message == "toast") { // make toast ... } }

Page 9: The art of Building Bridges for Android Hybrid Apps

loadUrl() Java  -­‐>  JavaScript  

Native JS

Quite  fast  Breaks  inputs  behaviour

<script type="text/javascript"> onLocationUpdate(int lat, int lng) { alert("Success: lat=" + lat + " lng: " + lng); } </script>

@Override public void onLocationChanged(Location location) { String lat = Double.toString(location.getLatitude()); String lng = Double.toString(location.getLongitude()); webView.loadUrl("javascript:onLocationUpdate(" + lat + "," + lng + ");"); }

Page 10: The art of Building Bridges for Android Hybrid Apps

Online  Event Java  -­‐>  JavaScript  

Native JS

It’s  fast  Even  faster  than  loadUrl()  

Doesn’t  break  anything  (yet)  Problem  in  case  of  bridging  more  than  one  WebView

<script type="text/javascript"> var handleEvent = function() { // get result from native code // using exposed interface }

window.addEventListener("online", handleEvent); window.addEventListener("offline", handleEvent); </script>

boolean flipFlop; // (...) @Override public void informJavaScriptAboutResult() { flipFlop = !flipFlop; webView.setNetworkAvailable(flipFlop); }

Page 11: The art of Building Bridges for Android Hybrid Apps

Private  APIJava  -­‐>  JavaScript  

Class webViewClass = WebView.class;

try { Field f = webViewClass.getDeclaredField("mProvider"); f.setAccessible(true); webViewObject = f.get(webView); webViewClass = webViewObject.getClass(); } catch (Throwable e) { // ... } try { Field f = webViewClass.getDeclaredField("mWebViewCore"); f.setAccessible(true); webViewCore = f.get(webViewObject);

if (webViewCore != null) { sendMessageMethod = webViewCore.getClass().getDeclaredMethod("sendMessage", Message.class); sendMessageMethod.setAccessible(true); } } catch (Throwable e) { // ... }

Be  careful  while  using  reflection…

Page 12: The art of Building Bridges for Android Hybrid Apps

Private  APIJava  -­‐>  JavaScript  

Native JS

Super  fast  Not  supported  officially  Works  on  Android  3.2+  May  break  in  the  future

<script type="text/javascript"> onLocationUpdate(int lat, int lng) { alert("Success: lat=" + lat + " lng: " + lng); } </script>

try { String js = "onLocationUpdate(" + lat + "," + lng + ");"; Message execJsMessage = Message.obtain(null, EXECUTE_JS, js); sendMessageMethod.invoke(webViewCore, execJsMessage); } catch (Throwable e) { // ... }

Page 13: The art of Building Bridges for Android Hybrid Apps

To  Sum  Up

Hybrid  is  the  future

Choose  proper  bridge

Page 14: The art of Building Bridges for Android Hybrid Apps

QA

Bartłomiej  Pisulak  Software  Engineer  |  IT  Trainer  http://www.pisulak.pl/