Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

NativeObject

NativeObject represents a platform-native object. More...

Import Statement: import Felgo 4.0
Since: Felgo 3.3.0
Inherited By:

NativeClass

Methods

  • var callMethod(string methodName, var parameters, enumeration threadType, function resultHandler)
  • NativeClass getClass()
  • var getProperty(string propertyName)
  • void setProperty(string propertyName, var value)

Detailed Description

This QML type allows you to interact with native objects on mobile platforms. NativeObject is currently supported on Android and iOS.

A NativeObject wraps an instance of a platform-native object. On Android, this is an instance of Object. On iOS, this is any Objective C id.

You can call methods of the underlying native object with callMethod(). You can also access fields/properties of the object with getProperty() and setProperty().

You can interact with native classes using the derived type NativeClass. It can call static methods and create new object instances. You can obtain a reference to the object's class with getClass(). Similarly, you can access any class by name with NativeObjectUtils::getClass().

NativeObject is intended for advanced usage. Most apps do not need to interact with native objects directly. The most common applications are available in NativeUtils.

This type allows you to directly call any native APIs. These APIs are platform-specific. So make sure to only call them on the correct platform. You can use the Qt global object to find out the currently running platform at runtime:

 if(Qt.platform.os === "android") {
   // android specific code
 }
 else if(Qt.platform.os === "ios") {
   // iOS specific code
 }

You can also safely call native APIs from within your NativeView platform binding implementations. Use the NativeView::androidBinding property for Android specific code and the NativeView::iosBinding for iOS specific code.

Usage Example

NativeObject is useful to add any native functionality to your apps or games that is not directly supported by Felgo. The following example shows how to get the current battery level on Android and iOS.

A public method handles the platform detection: It uses Qt.platform.os to find out the current platform. It then calls a platform-dependent private method.

The platform-dependent methods can use NativeObjectUtils::getClass() to access native classes. They can create new instances of these classes with NativeClass::newInstance(). They can then call methods of an object instance with callMethod(). Also they can access Java fields and Objective C properties with getProperty() and setProperty().

 import Felgo
 import QtQuick

 App {
   AppButton {
     anchors.centerIn: parent
     text: qsTr("Check Battery")
     onClicked: {
       var batteryPercent = Math.round(getBatteryLevel() * 100)
       text = "Battery: "+ batteryPercent + "%"
     }
   }

   // returns battery level between 0 and 1 on mobile platforms
   function getBatteryLevel() {
     // call platform-dependent implementation:
     if(Qt.platform.os === "android") {
       return _.getAndroidBatteryLevel()
     }
     else if(Qt.platform.os === "ios") {
       return _.getIosBatteryLevel()
     }
     else {
       return 0
     }
   }

   // private methods
   Item {
     id: _

     function getAndroidBatteryLevel() {
       // imports and constants:
       var Intent = NativeObjectUtils.getClass("android/content/Intent")
       var IntentFilter = NativeObjectUtils.getClass("android/content/IntentFilter")
       var BatteryManager = NativeObjectUtils.getClass("android/os/BatteryManager")

       var context = NativeObjectUtils.getContext()

       // Corresponding Java code (from https://developer.android.com/training/monitoring-device-state/battery-monitoring#CurrentLevel):
       // IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
       // Intent batteryStatus = context.registerReceiver(null, ifilter);
       // int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
       // int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
       // return level / (float)scale;

       var filter = IntentFilter.newInstance(Intent.getStaticProperty("ACTION_BATTERY_CHANGED"))
       var batteryStatus = context.callMethod("registerReceiver", [null, filter])

       var level = batteryStatus.callMethod("getIntExtra", [BatteryManager.getStaticProperty("EXTRA_LEVEL"), -1])
       var scale = batteryStatus.callMethod("getIntExtra", [BatteryManager.getStaticProperty("EXTRA_SCALE"), -1])

       return level / scale
     }

     function getIosBatteryLevel() {
       // imports:
       var UIDevice = NativeObjectUtils.getClass("UIDevice")

       // Corresponding Objective C code:
       // UIDevice *device = UIDevice.currentDevice;
       // device.batteryMonitoringEnabled = YES;
       // return device.batteryLevel;

       var device = UIDevice.getStaticProperty("currentDevice")
       device.setProperty("batteryMonitoringEnabled", true)
       return device.getProperty("batteryLevel")
     }
   }
 }

Data Type Conversions between QML and Native Code

The methods in NativeObject perform conversion between QML/JavaScript and native object types. They convert parameters, property values and return values automatically.

This table describes which type conversions they perform:

JavaScript / QML Android iOS
Bool boolean BOOL
Number Any primitive number type,
java.lang.Number
Any primitive number type,
NSNumber
String java.lang.String,
java.lang.CharSequence
NSString,
SEL
Array java.util.List,
T[]
NSArray
Object java.util.Map NSDictionary
function,
map of functions
any interface type any @protocol type
NativeObject java.lang.Object NSObject,
id
null,
undefined
null null,
NSNull

When you pass an object from QML to a native method/property, you can use it for any of the listed types. For example, a JavaScript array can be used to call a Java method with a java.util.List parameter. However it can also be used for a method that accepts a regular Java array.

When you retrieve an object from a native method/property, it is converted to the corresponding JavaScript type. Any object that is not directly supported by a QML type as listed in the table is returned as a new NativeObject instance.

Interfaces and Protocols

When you interact with native objects, it is often necessary to create objects conforming to Java interfaces and Objective C protocols.

On Android for example, to get a click event from a android.widget.Button, you need an OnClickListener implementation. The implementation needs to implement the onClick(View view) method.

You can do this by supplying a JavaScript function. For example, you can use this code to set the Button.onClickListener:

 view.callMethod("setOnClickListener", function(v) {
   // call QML signal:
   parent.clicked()
 })

Note: NativeObject does currently not support returning values from a JavaScript function to a Java interface method. Any Java interface method will return null, regardless of what you return from your JavaScript function. It does however support returning a value from JavaScript to an Objective C protocol method.

You can also create a JavaScript object with keys mapping to functions in place of a Java interface. This is useful if you need to implement multiple interface methods. Each key in the supplied object corresponds to a method with that name in the interface. Example:

 view.callMethod("setOnClickListener", {
   "onClick": function(v) {
     // call QML signal:
     parent.clicked()
   }
   // could add additional interface methods here
 })

On iOS, you can use the same method to create objects conforming to Objective C protocols. You can use this to create delegate objects and to add target actions.

iOS: Object Lifetime

Native objects in Objective C use manual reference counting to manage their lifetime. Delegate properties usually only store a weak reference without incrementing the reference count.

Thus when obtaining a wrapper for a native protocol, you can store a strong reference manually. Use the NativeObjectUtils::wrap() method for this. It returns a reference that is managed by the QML engine's garbage collector. You can store it in a property for as long as you use it as a delegate for another object.

Example adding a UIScrollViewDelegate:

 Item {
   property NativeObject scrollView // UIScrollView instance

   // create wrapper for UIScrollViewDelegate and store strong reference:
   property NativeObject scrollViewDelegate: NativeObjectUtils.wrap({
     "scrollViewWillBeginDragging:": function(scrollView) {
       console.log("begin dragging")
     },
     // ...other delegate methods here
   })

   function initScrollView() {
     // ...obtain scrollView instance

     scrollView.setProperty("delegate", scrollViewDelegate)
   }
 }

Method Signatures

In Objective C, protocol methods have defined method signatures. When you add a method in such a protocol implementation, you can specify the method signature before the method name. You can omit the method signature if all parameters and the return value are of object type (id or pointer to NSObject types).

Example adding a UIScrollViewDelegate with methods that use non-object parameters:

 Item {
   property NativeObject scrollView // UIScrollView instance

   // create wrapper for UIScrollViewDelegate and store strong reference:
   property NativeObject scrollViewDelegate: NativeObjectUtils.wrap({
     // method signature can be omitted - only object parameters and return type
     "scrollViewWillBeginDragging:": function(scrollView) {
       console.log("begin dragging")
     },
     // manual method signature required because of non-object parameter bool decelerate
     "v@:@B scrollViewDidEndDragging:willDecelerate:": function(scrollView, decelerate) {
       console.log("end dragging", decelerate)
     },
     "scrollViewDidEndDecelerating:": function(scrollView) {
       console.log("end decelerating")
     }
   })

   function initScrollView() {
     // ...obtain scrollView instance

     scrollView.setProperty("delegate", scrollViewDelegate)
   }
 }

Available QML Items

NativeClass

Represents a platform-native class

NativeObject

Represents a platform-native object

NativeObjectUtils

Allows you to interact with objects native to the mobile platform

NativeView

Allows to instantiate and display platform-specific views and widgets

NativeViewBinding

Defines the platform specifics for NativeView

Method Documentation

var callMethod(string methodName, var parameters, enumeration threadType, function resultHandler)

Calls the method methodName on the native object represented by this item.

On Android, it considers all overloads of this method. It converts the supplied parameters according to Data Type Conversions between QML and Native Code. If any overload fits the converted parameters, it calls that overload.

On iOS, the methodName is the full selector of the method you want to call, including the colons. Example: "addTarget:action:forControlEvents:" for UIButton actions.

You can supply parameters to the method call with the optional parameter parameters. It can be either a single parameter object or a JavaScript array of parameters.

You can specify which thread to call the method on with the optional parameter threadType. Use one of these enumeration values with it:

  • NativeObject.CurrentThread - Calls the method directly on the QML thread.
  • NativeObject.UiThread - Calls the method in the platform's native UI thread.

    Note: When calling methods of View objects, this thread type should usually be preferred.

    Note: On iOS, QML applications run directly on the UI thread. This means, CurrentThread and UiThread will result in the same behavior.

  • NativeObject.BackgroundThread - Calls the method asynchronously in a background thread.

You can use the optional parameter resultHandler to obtain the method return value asynchronously.

You can supply a JavaScript function for resultHandler. callMethod() then immediately returns an undefined value. It then calls the resultHandler function after the method call has finished. It supplies the method return value as first parameter to the function.

You can also omit resultHandler. In this case, callMethod() returns the method return value directly. If the call is executed on another thread, this means the QML thread will be blocked during that time.

See also NativeClass::callStaticMethod().


NativeClass getClass()

Returns a NativeClass object representing this object's class.

This is equivalent to calling object.getClass() on Android and [object class] on iOS.

See also NativeObjectUtils::getClass().


var getProperty(string propertyName)

Get the property propertyName from the native object represented by this item.

On Android, this reads a field in the native object's class. If no field with this name exists or the field is not public, it logs a warning message and returns an undefined value.

On iOS, this reads an Objective C property in the native object's class. If no property with this name exists, it logs a warning message and returns an undefined value.

See also setProperty and NativeClass::setStaticProperty().


void setProperty(string propertyName, var value)

Set the property propertyName from the native object represented by this item to value.

On Android, this sets a field in the native object's class. If no field with this name exists or the field is not public, it logs a warning message and does nothing.

On iOS, this sets an Objective C property in the native object's class. If no property with this name exists, it logs a warning message and does nothing.

See also getProperty and NativeClass::getStaticProperty().


Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded