Use Crosswalk extensions with the embedding API
Extensions are supported in version 2.1 and later of the embedding API. The extensions API is similar to the one for Crosswalk runtime extensions, but with a few differences due to the usage model of an embedding application (i.e. an Android application which embeds Crosswalk using Java code):
- There is no support for lifecycle events. The extension cannot use
onResume(),onPause(),onDestroy(), oronActivityResult(). Such events should be taken care of by the embedding application. - No configuration file is needed, because the embedding application is responsible for creating and destroying the extensions in Java code.
- No support for [
make_apk.py]. The embedding application is likely to be built using Android SDK tools, ant etc.; the extension code should be compiled and packaged as part of this build.
The following sections explain how to add code for an extension and use it in an embedding application. Before following them, you will need to create an application with the embedding API.
Write the extension
Create a Java class which extends XWalkExtension. For example:
org/crosswalkproject/sample/ExtensionEcho.java:
package org.crosswalkproject.sample;
import org.xwalk.core.XWalkExtension;
public class ExtensionEcho extends XWalkExtension {
private static String name = "echo";
private static String jsapi = "var echoListener = null;" +
"extension.setMessageListener(function(msg) {" +
" if (echoListener instanceof Function) {" +
" echoListener(msg);" + " };" + "});" +
"exports.echo = function (msg, callback) {" +
" echoListener = callback;" + " extension.postMessage(msg);" +
"};" + "exports.echoSync = function (msg) {" +
" return extension.internal.sendSyncMessage(msg);" + "};";
public ExtensionEcho() {
super(name, jsapi);
}
@Override
public void onMessage(int instanceID, String message) {
postMessage(instanceID, "From java: " + message);
}
@Override
public String onSyncMessage(int instanceID, String message) {
return "From java sync: " + message;
}
}
This extension only does some basic string manipulation, but a real extension could make use of the full range of Android APIs, as well as any imported Java libraries.
Some hints about the code:
The JavaScript string in the constructor can be passed in different ways: it could be passed in as a
String(as done here), read from a.jsfile in theassets/directory, fetched from a web server, etc.The string returned by the
onMessage()andonSyncMessage()methods could be serialised to/from JSON to handle more complex interactions. See the runtime extension documentation for details.
Note that it is also possible to include an extension in binary format, in a jar or .class file bundled with the embedding application. Extensions included by the embedding application can be used the same way as any other imported Java classes.
Use the extension in the embedding application
To use the extension, you need to initialise it just after the embedding application's main activity is started. For example, if your activity was src/org/crosswalkproject/sample/MainActivity.java (see the embedding tutorial), you could use the extension as follows:
Add code to the main activity to create an instance of the extension when the activity is ready:
import org.crosswalkproject.sample.ExtensionEcho; public class MainActivity extends Activity { private XWalkView mXWalkView; private ExtensionEcho mExtension; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // here is where the extension instance is created mExtension = new ExtensionEcho(); // create the main Crosswalk view mXWalkView = (XWalkView) findViewById(R.id.activity_main); mXWalkView.load("file:///android_asset/index.html", null); } }Note that it is recommended that you create extensions before creating the
XWalkViewinstance.Also note that if you create multiple instances of an extension with the same name (
"echo"in the example above), only the first has any effect. Any subsequent instances you create will not have any effect (the C++ code in Crosswalk ignores an attempt to add an extension which has the same name as an existing one).Use the extension from JavaScript in the web part of the application. The following code performs a simple test on the extension and writes the result into a paragraph element:
<script> try { var now = new Date().toString(); // test the async API of the extension echo.echo(now, function (msg) { var p1 = document.createElement('p'); p1.innerHTML = msg + "<br>"; document.body.appendChild(p1); var expected = "From java:" + now; var p2 = document.createElement('p'); if (msg === expected) { p2.innerHTML = 'Async echo <span style="color:green;">passed</span>.'; document.title = 'Pass'; } else { p2.innerHTML = 'Async echo <span style="color:red;">failed</span>.'; document.title = 'Fail'; } document.body.appendChild(p2); }); } catch (e) { console.log(e); document.title = "Fail"; } </script>
English
