Tour Preview

Find the Best Demos and Examples

Check out this quick tour to find the best demos and examples for you, and to see how the Felgo SDK can help you to develop your next app or game!

FelgoAndroidFragment

FelgoAndroidFragment shows Felgo QML content in a native Android application. More...

Import Statement: import Felgo 3.0
Since: Felgo 3.7.0

Methods

Detailed Description

This item is available in native Android code.

FelgoAndroidFramgent can load and show Felgo QML content from within a native Android application. Any Activity in your app that shows an instance of FelgoAndroidFragment should be a subclass of FelgoAndroidActivity.

Add QML Files to Your Project

You can load QML files from anywhere. All you need is the text content of the QML file. This lets you even load QML files from the web at runtime.

The most common use case is loading QML files from your project assets. To do so, place your .qml files under your projects assets directory (usually <project-dir>/src/main/assets). You can also use subfolders inside assets and reference files relatively from within QML.

Load QML Content

You can load any QML content using the class FelgoAndroidFragment. You can add an instance of the Fragment in code or in a layout XML file.

Using a Layout XML File

You can add FelgoAndroidFragment to any layout .xml file:

 <fragment
     android:id="@+id/qt_fragment_container"
     class="com.felgo.ui.FelgoAndroidFragment"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     app:qml_source="qml/Main.qml"/>

This loads the file qml/Main.qml from your project assets.

Using FragmentManager

To programmatically add a FelgoAndroidFragment to an Activity, you can use FragmentManager:

 void loadQml() {
   try {
     getFragmentManager().beginTransaction()
         .replace(R.id.fragment_container, new FelgoAndroidFragment()
                 .setQmlSource(getApplicationContext(), "qml/Main.qml"),
             null)
         .addToBackStack(null)
         .commit();
   } catch (IOException ex) {
     // QML file not found
     Log.w("MainActivity", "Could not load QML file", ex);
   }
 }

Here R.id.fragment_container is the ID of an existing view to place the new Fragment into. This loads the file qml/Main.qml from your project assets. You can also load content from other places.

Use the method FelgoAndroidFragment.setQmlSource(Context context, var source) to load QML from a local file. The source parameter can be any file:// URI. In this case, relative resource lookup within QML starts at the source file's directory. To load a file from your app's assets, use a String with the asset file path. For example, a call like setQmlSource(context, "qml/Main.qml").

Use the method FelgoAndroidFragment.setQmlContent(String qmlContent, String qmlBaseUrl) to load QML content directly from a source string. The parameter qmlBaseUrl is an optional virtual URL for relative resource lookup within QML. For example, you can use file:///android_asset/qml/Main.qml as base URL. This lets you use lookup e.g. "../images/image.png" from within QML. Which would result in the image being loaded from your app's assets/images folder.

Interact with QML

You can interact with the QML application directly from native code. FelgoAndroidFragment provides methods for this. You can read and write properties on the QML root item with setQmlProperty() and getQmlProperty(). You can call a JavaScript function on the root item with callQmlMethod(). You can react to QML signals with addSignalHandler().

Note: On Android, the QML application runs on a thread separate from the Android UI thread. Thus setting QML properties and calling QML methods happens asynchronously. Also, signal handlers are not invoked on the UI thread. To interact with native UI from signal handlers, you can use Activity.runOnUiThread().

You can use these methods after loading a QML file with either setQmlSource() or setQmlContent(). The QML scene is loaded asynchronously. You can react to the QML file being loaded completely from your native app. Either override FelgoAndroidActivity::onQmlInitialized() or use FelgoAndroidFragment::setQmlInitializedListener(). The callbacks are invoked on the Android UI thread.

Example

The following example shows how to set up interaction between Java and QML:

assets/qml/Main.qml

 import Felgo 3.0
 import QtQuick 2.12

 App {
     property string qmlText: ""

     signal btnPressed

     Column {
         AppText {
             text: qmlText
         }

         AppButton {
             text: "Click me!"
             onClicked: btnPressed()
         }
     }
 }

MainActivity.java

 package com.felgo.nativeintegrationexample;

 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.v7.widget.Toolbar;
 import android.util.Log;

 import com.felgo.ui.FelgoAndroidActivity;
 import com.felgo.ui.FelgoAndroidFragment;

 import org.qtproject.qt5.android.bindings.QtFragment;

 import java.io.IOException;

 public class MainActivity extends FelgoAndroidActivity {

   private FelgoAndroidFragment m_felgo;

   @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);

     m_felgo = new FelgoAndroidFragment();

     // show QML fragment and load assets/qml/Main.qml:
     try {
       m_felgo.setQmlSource(getApplicationContext(), "qml/Main.qml");
     } catch (IOException ex) {
       // qml file not found
       Log.w("MainActivity", "Could not load QML file", ex);
     }

     getSupportFragmentManager().beginTransaction()
         .replace(android.R.id.content, m_felgo,null)
         .addToBackStack(null)
         .commit();
   }

   @Override
   public void onQmlInitialized() {
     m_felgo.setQmlProperty("qmlText", "Hello QML from Java!");

     m_felgo.addSignalHandler("btnPressed", new QtFragment.QmlSignalHandler() {
       @Override
       public void onSignalEmitted(Object[] signalParameters) {
         Log.d("MainActivity", "QML button pressed!");
       }
     });
   }
 }

For more information, see Integrate Felgo with Existing Applications.

Method Documentation

void addSignalHandler(name, Object handler)

Adds a signal handler on the QML root element. Use an implementation of QmlSignalHandler as parameter.

For example, if you loaded this QML file:

 App {
   signal mySignal(string param)
 }

Then you can add a signal handler with this code:

 felgoFragment.addSignalHandler("mySignal", new QtFragment.QmlSignalHandler() {
   @Override
   public void onSignalEmitted(Object[] objects) {
     Log.d("Felgo Examples", "mySignal emitted with param: " + objects[0]);
   }
 });

Note: This method should only be called from or after the setQmlInitializedListener callback.

See also getQmlProperty(), setQmlProperty(), and callQmlMethod().


void callQmlMethod(name, Object... params)

Calls any JavaScript function on the QML root element.

For example, if you loaded this QML file:

 App {
   function hello(p1, p2) {
     console.log("Hello JS!", p1, p2)
   }
 }

Then you can call the function with this code:

 felgoFragment.callQmlMethod("hello", "P1 value", "P2 value");
 // output: "Hello JS! P1 value P2 value"

Note: This method should only be called from or after the setQmlInitializedListener callback.

See also getQmlProperty(), setQmlProperty(), and addSignalHandler().


Object getQmlProperty(name)

Returns the value of any property on the QML root element.

For example, if you loaded this QML file:

 App {
   property string message: "Hello Felgo!"
 }

Then you can read the property value with this code:

 String message = felgoFragment.getQmlProperty("message");
 // message now contains "Hello Felgo!"

Note: This method should only be called from or after the setQmlInitializedListener callback.

See also setQmlProperty(), callQmlMethod(), and addSignalHandler().


void setQmlContent(qmlContent, String qmlBaseUrl)

Sets the QML file content to load. Call this method before adding the Fragment with FragmentManager.

The qmlContent should contain the whole QML file, including imports.

The qmlBaseUrl is an optional virtual URL for relative resource lookup within QML. For example, you can use file:///android_asset/qml/Main.qml as base URL. This lets you use lookup e.g. "../images/image.png" from within QML. Which would result in the image being loaded from your app's assets/images folder.

Note: The file specified for qmlBaseUrl does not actually have to exist. Only its folder should exist.

To load a file from your app's assets, use an URL like file:///android_asset/Main.qml.

See also setQmlSource().


void setQmlInitializedListener(listener)

You can use this property to provide code that is called after the QML file has been loaded.

Set it to an implementation of QmlInitializedListener, for example:

 felgoFragment.setQmlInitializedListener(new FelgoAndroidFragment.QmlInitializedListener() {
   @Override
   public void onQmlInitialized() {
     Log.d("Felgo Examples", "QML initialized!");
   }
 });

void setQmlProperty(name, Object value)

Sets any property on the QML root element.

For example, if you loaded this QML file:

 App {
   property string message: "Hello Felgo!"
 }

Then you can write the property value with this code:

 felgoFragment.setQmlProperty("message", "Hello Android!");
 // QML property now contains "Hello Android!"

Note: This method should only be called from or after the setQmlInitializedListener callback.

See also getQmlProperty(), callQmlMethod(), and addSignalHandler().


void setQmlSource(context, var source)

Sets the QML file to load. Call this method before adding the Fragment with FragmentManager.

The source parameter can be any file:// URI. Relative resource lookup within QML starts at the source file's directory.

To load a file from your app's assets, use an URI starting with file:///android_asset/. As a shorthand, you can also pass a String instead of an URI with an asset file name. This means calling setQmlSource(context, URI.create("file:///android_asset/qml/Main.qml")) is equivalent to calling setQmlSource(context, "qml/Main.qml").

See also setQmlContent().