hybrid apps: java conversing with javascript
TRANSCRIPT
Hybrid Apps with Angular: Java
conversing with JavaScriptAyman Mahfouz
VP of Engineering @ Webalo
September 2016
Problem Context - Webalo App
Shared Java code allows for extensibility, but how to open the Webalo Client up for third party extension?
Solution - Hybrid App
HTML + JavaScript
Java
WebView
Android App
● Java: Proprietary code.● JavaScript: Third-party code.
Java to JavaScript
API
void evaluateJavascript(String script, ValueCallback<String> resultCallback)
webView.evaluateJavascript(“someJavaScriptFunction();”, new ValueCallback<String>() {
public void onReceiveValue(String s) { JsonReader reader = new JsonReader(new StringReader(s));
JsonToken token = JsonReader.peek() ... }});
Usage
Java to JavaScript
Requirements
1. API level 19.2. WebSettings.setJavaScriptEnabled(true) // false by default3. Must be called on UI thread.
evaluateJavascript(...)
Properties
1. Asynchronous evaluation.2. Context of currently displayed page.3. Callback made on UI thread.4. Callback value is a JSON object. To pass String values use
JsonReader.setLenient(true).
Java to JavaScript - Pre 19
void loadUrl(String url)
Usage
webView.loadUrl(“javascript:someJsFunction();”);
API
Pitfall - Navigate away
webView.loadUrl(“javascript:someJsFunction();void(0);”);
No return value!
JavaScript to Java
Inject objects into the displayed page context:
private final class Api {
public void showMessage(String message) { Log.d(TAG, message); }}webView.addJavascriptInterface(new Api(), "MyJavaObj");
Starting API 17
void addJavascriptInterface(Object serviceApi, String name)
Usage
API
MyJavaObj.showMessage(“Hello GDG!”);
Java
JS
@JavascriptInterface
JavaScript to Java - Notes
1. Injected objects will not appear in JavaScript until the page is next (re)loaded.
webView.loadData("", "text/html", null);
2. WebView interacts with Java object on a background thread. 3. Serialization of arguments
a. Simple types and stringsb. Serialize objects as JSON
4. Use WebChromeClient to handle callbacks
webView.setWebChromeClient(new WebChromeClient() { public boolean onJsAlert(...) { // display alert in OS theme } }); }
Troubleshooting
Use Chrome “Inspect” feature
chrome://inspectMust enable debugging
WebView.setWebContentsDebuggingEnabled(true);
[INFO:CONSOLE(1)] "Uncaught SyntaxError: Unexpected token ILLEGAL", source: (1)[INFO:CONSOLE(13)] "Uncaught ReferenceError: MyJavaObj is not defined"android.view.ViewRootImpl$CalledFromWrongThreadException
1. Run calls from JavaScript on UI Thread. 2. Wait till page loads WebViewClient.onPageFinished()3. Force page load using
webView.loadData("", "text/html", null);
Debugging
Common Causes
Common Errors
Angular to Java
Wrap an Angular service around the injected Java Object.
angular.module('MyModule').service('WrapperService', function() { this.showMessage = function(message) { MyJavaObj.showMessage(message); };
this.someOtherMethod = function() { MyJavaObj.someOtherMethod(); };});
Java to Angular
// Get the element for the angular applicationvar app = angular.element('[ng-app]');
// Get the injector from the application var injector = app.injector();
// Get the service to be calledvar myService = injector.get("MyService");
// Invoke the servicemyService.someFunction();
What is the entry point from plain JavaScript to Angular?
linkedin.com/in/amahfouz
aymanmahfouz.blogspot.com
slideshare.net/AymanMahfouz
github.com/amahfouz
Demo & Questions