This document discusses how to create hybrid apps that combine Java and JavaScript using Angular and WebViews. It provides solutions for allowing communication between Java and JavaScript code, in both directions. This is achieved by injecting Java objects into the JavaScript context and calling JavaScript functions from Java. Angular services can wrap the injected Java objects to make them available to Angular applications. Getting the Angular injector allows calling Angular services from plain JavaScript. Troubleshooting tips are also provided for common errors like reference errors and threading issues.
6. 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
7. Java to JavaScript
Requirements
1. API level 19.
2. WebSettings.setJavaScriptEnabled(true) // false by default
3. 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).
8. 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!
10. 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!”);
JavaJS
@JavascriptInterface
11. 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 strings
b. Serialize objects as JSON
4. Use WebChromeClient to handle callbacks
webView.setWebChromeClient(new WebChromeClient() {
public boolean onJsAlert(...) {
// display alert in OS theme
}
});
}
12. Troubleshooting
Use Chrome “Inspect” feature
chrome://inspect
Must 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
14. 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();
};
});
15. Java to Angular
// Get the element for the angular application
var app = angular.element('[ng-app]');
// Get the injector from the application
var injector = app.injector();
// Get the service to be called
var myService = injector.get("MyService");
// Invoke the service
myService.someFunction();
What is the entry point from plain JavaScript to Angular?