the art of building bridges for android hybrid apps
TRANSCRIPT
![Page 1: The art of Building Bridges for Android Hybrid Apps](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/1.jpg)
The Art of Building Bridges
Android WebView Bridge in Depth
Bartłomiej Pisulak
![Page 2: The art of Building Bridges for Android Hybrid Apps](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/2.jpg)
Three types of Mobile Apps
![Page 3: The art of Building Bridges for Android Hybrid Apps](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/3.jpg)
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](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/4.jpg)
ArchitectureIt’s all about WebView…
So what’s the difference?
![Page 5: The art of Building Bridges for Android Hybrid Apps](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/5.jpg)
The Bridge
Bridge between Native and JS
JS -‐> Native Native -‐> JS
![Page 6: The art of Building Bridges for Android Hybrid Apps](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/6.jpg)
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](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/7.jpg)
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](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/8.jpg)
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](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/9.jpg)
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](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/10.jpg)
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](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/11.jpg)
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](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/12.jpg)
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](https://reader033.vdocuments.net/reader033/viewer/2022042818/55c52c86bb61eb5f4d8b46a8/html5/thumbnails/13.jpg)
To Sum Up
Hybrid is the future
Choose proper bridge