Invoking Native Code
You can invoke native code from JavaScript using NativeObject, whether it’s platform APIs, third-party code, or your own custom native code. For the latter two cases, you need to include the code in your project. Include Native Code in Your ProjectCordova apps with Ace installed can include any native code and resources in the project’s native folder. Code and resources placed here gets compiled into your project: Using NativeObject to Invoke Native CodeHere are the ways to do it: // Instantiate a native class with its default constructor var obj = new ace.NativeObject("NameOfNativeClass"); // Instantiate a native class with a parameterized constructor var obj = new ace.NativeObject("NameOfNativeClass", 5); // Invoke an instance method obj.invoke("Method1"); // Invoke an instance method with two parameters obj.invoke("Method2", 12, 24); // Invoke an instance method and retrieve its return value obj.invoke("Method1", function(returnValue) { /* ... */ }); // Invoke an instance method with one parameter and retrieve its return value obj.invoke("Method1", "param", function(returnValue) { /* ... */ }); // Get an instance field value (doesn't apply to iOS) obj.getField("Field1", function(value) { /* ... */ }); // Set an instance field value (doesn't apply to iOS) obj.setField("Field1", 7); // Invoke a static method ace.NativeObject.invoke("NameOfNativeClass", "Method1"); // Invoke a static method with two parameters ace.NativeObject.invoke("NameOfNativeClass", "Method2", 12, 24); // Invoke a static method and retrieve its return value ace.NativeObject.invoke("NameOfNativeClass", "Method1", function(returnValue) { /* ... */ }); // Invoke a static method with one parameter and retrieve its return value ace.NativeObject.invoke("NameOfNativeClass", "Method1", "param", function(returnValue) { /* ... */ }); // Get a static field value (doesn't apply to iOS) ace.NativeObject.getField("NameOfNativeClass", "Field1", function(value) { /* ... */ }); // Set a static field value (doesn't apply to iOS) ace.NativeObject.setField("NameOfNativeClass", "Field1", 7); Writing Platform-Specific CodeWhen you directly invoke native APIs, the code you write will be platform-specific. See this topic for details and strategies for writing platform-specific code. Real-World ExamplesShowing the battery level on iOS and Android function invokeBattery() { if (ace.platform == "iOS") { // Objective-C code: // UIDevice* device = [UIDevice currentDevice]; // [device setBatteryMonitoringEnabled:true]; // double capacity = [device batteryLevel] * 100; // Invoke a static currentDevice method on UIDevice ace.NativeObject.invoke("UIDevice", "currentDevice", function (device) { // On the returned instance, call an instance method with no return value device.invoke("setBatteryMonitoringEnabled", true); // Call another instance method that returns a double device.invoke("batteryLevel", function (level) { alert("capacity = " + (level * 100) + "%"); }); }); } else if (ace.platform == "Android") { // Java code: // BatteryManager batteryManager = getContext().getSystemService(Context.BATTERY_SERVICE); // int capacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); // Get the value of the string constant Context.BATTERY_SERVICE ace.NativeObject.getField("android.content.Context", "BATTERY_SERVICE", function (constant) { // Invoke an instance method on the Android context object to get a BatteryManager instance ace.android.getContext().invoke("getSystemService", constant, function (batteryManager) { ace.NativeObject.getField("android.os.BatteryManager", "BATTERY_PROPERTY_CAPACITY", function (constant) { batteryManager.invoke("getIntProperty", constant, function (value) { alert("capacity = " + value + "%"); }); }); }); }); } } Showing the current screen’s width, height, and DPI on Android if (ace.platform == "Android") { // // WindowManager windowManager = getContext().getSystemService(Context.WINDOW_SERVICE); // Display display = windowManager.getDefaultDisplay(); // Display metrics = new DisplayMetrics(); // display.getMetrics(metrics); // int dpi = metrics.densityDpi; // int w = metrics.widthPixels; // int h = metrics.heightPixels; // ace.NativeObject.getField("android.content.Context", "WINDOW_SERVICE", function (constant) { ace.android.getContext().invoke("getSystemService", constant, function (windowManager) { windowManager.invoke("getDefaultDisplay", function (display) { var metrics = new ace.NativeObject("android.util.DisplayMetrics"); display.invoke("getMetrics", metrics); metrics.getField("densityDpi", function (dpi) { metrics.getField("widthPixels", function (w) { metrics.getField("heightPixels", function (h) { alert(dpi + " DPI, and " + w + "px by " + h + "px"); }); }); }); }); }); }); } Showing device info on iOS if (ace.platform == "iOS") { // // UIDevice* device = [UIDevice currentDevice]; // NSString* name = [device name]; // NSString* systemName = [device systemName]; // NSString* systemVersion = [device systemVersion]; // ace.NativeObject.invoke("UIDevice", "currentDevice", function (device) { device.invoke("name", function (value) { alert("name = " + value) }); device.invoke("systemName", function (value) { alert("systemName = " + value) }); device.invoke("systemVersion", function (value) { alert("systemVersion = " + value) }); }); } Vibrating in a pattern on Android You must add <uses-permission android:name=”android.permission.VIBRATE” /> to your AndroidManifest.xml for this to work. if (ace.platform == "Android") { var pattern = [0, 500, 110, 500, 110, 450, 110, 200, 110, 170, 40, 450, 110, 200, 110, 170, 40, 500]; // The shorter way: // // Vibrator vibrator = getContext().getSystemService("vibrator"); // vibrator.vibrate(pattern, -1); // ace.android.getContext().invoke("getSystemService", "vibrator", function (vibrator) { vibrator.invoke("vibrate", pattern, -1); }); // The longer way: // // Vibrator vibrator = getContext().getSystemService(Context.VIBRATOR_SERVICE); // vibrator.vibrate(pattern, -1); // ace.NativeObject.getField("android.content.Context", "VIBRATOR_SERVICE", function (constant) { ace.android.getContext().invoke("getSystemService", constant, function (vibrator) { vibrator.invoke("vibrate", pattern, -1); }); }); } Having fun with proximity monitoring on iOS if (ace.platform == "iOS") { // // UIDevice* device = [UIDevice currentDevice]; // [device setProximityMonitoringEnabled:true]; // BOOL isClose = [device proximityState]; // ace.NativeObject.invoke("UIDevice", "currentDevice", function (device) { if (proximityHandle == null) { $("#spotForProximityOutput").html("<h2>Monitoring proximity...</h2>"); // Turn on proximity monitoring device.invoke("setProximityMonitoringEnabled", true); // Check the status once a second proximityHandle = setInterval(function () { device.invoke("proximityState", function (isClose) { if (isClose) { // The user is close $("<h2>CLOSE!</h2>").appendTo($("#spotForProximityOutput")); } }); }, 1000); } else { // Stop checking the status clearInterval(proximityHandle); proximityHandle = null; // Turn off proximity monitoring device.invoke("setProximityMonitoringEnabled", false); $("<h2>Monitoring stopped.</h2>").appendTo($("#spotForProximityOutput")); } }); } Using the Android Palette API to detect colors in an image For this to work, you must add a reference to the com.android.support:palette-v7 library. function usePalette() { // Set up a spot for showing palette results var popup = new ace.Popup(); popup.setContent(new ace.StackPanel()); popup.show(); if (ace.platform == "Android") { // // AssetManager assetManager = getContext().getAssets(); // InputStream inputStream = assetManager.open("www/images/poster.jpg"); // Bitmap bitmap = BitmapFactory.decodeStream(inputStream); // Palette.Builder paletteBuilder = Palette.from(bitmap); // Palette palette = paletteBuilder.generate(); // showPaletteButton(...); // ace.android.getContext().invoke("getAssets", function (assetManager) { assetManager.invoke("open", "www/images/poster.jpg", function (inputStream) { ace.NativeObject.invoke("android.graphics.BitmapFactory", "decodeStream", inputStream, function (bitmap) { ace.NativeObject.invoke("android.support.v7.graphics.Palette", "from", bitmap, function (paletteBuilder) { paletteBuilder.invoke("generate", function (palette) { showPaletteButton("getVibrantSwatch", palette, popup); showPaletteButton("getMutedSwatch", palette, popup); showPaletteButton("getLightVibrantSwatch", palette, popup); showPaletteButton("getLightMutedSwatch", palette, popup); showPaletteButton("getDarkVibrantSwatch", palette, popup); showPaletteButton("getDarkMutedSwatch", palette, popup); }); }); }); }); }); } } function showPaletteButton(methodName, palette, popup) { // // Swatch swatch = palette. |