FelgoAndroidView shows Felgo QML content in a native Android application. More...
Import Statement: | import Felgo 4.0 |
Since: | Felgo 3.10.0 |
This Native App Integration item is available in native Android code.
FelgoAndroidView can load and show Felgo QML content from within a native Android application. You can use this view like any other android View. Add it via layout XML file or programmatically.
To show QML content from a Fragment
instead, use FelgoAndroidFragment.
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.
Note: Use App or GameWindow as the root type for showing QML content.
You can load any QML content using the class FelgoAndroidView. You can add an instance of the Fragment in code or in a layout XML file.
You can add FelgoAndroidView to any layout .xml
file:
<com.felgo.ui.FelgoAndroidView android:id="@+id/felgo_view" 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.
You can also add a FelgoAndroidView programmatically at runtime:
void loadQml() { ViewGroup container = this.findViewById(R.id.felgo_container); try { container.addView(new FelgoAndroidView(this) .setQmlSource(getApplicationContext(), "qml/Main.qml") ); } catch (IOException ex) { // QML file not found Log.w("MainActivity", "Could not load QML file", ex); } }
Here R.id.felgo_container
is the ID of an existing ViewGroup
to place the new View into. This loads the file qml/Main.qml
from your project assets. You can also load content from other
places.
Use the method 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 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.
You can interact with the QML application directly from native code. FelgoAndroidView
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 FelgoAndroidView::setQmlInitializedListener(). The callbacks are invoked on the Android UI thread.
The following example shows how to set up interaction between Java and QML:
assets/qml/Main.qml
import Felgo import QtQuick 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.FelgoAndroidView; import org.qtproject.qt5.android.bindings.QtFragment; import java.io.IOException; public class MainActivity extends FelgoAndroidActivity { private FelgoAndroidView m_felgo; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); m_felgo = new FelgoAndroidView(this); // 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); } ViewGroup container = this.findViewById(R.id.felgo_container); container.addView(m_felgo); } @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 Native App Integration: Integrate Felgo and Qt with Existing Android and iOS Applications.
void addSignalHandler(String name, Object handler) |
Adds a signal handler on the QML root element. The name parameter specifies the QML signal that will be handled by the handler function.
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(String name, Object... params) |
Calls the QML root element JavaScript function specified by name with a list of params.
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(String name) |
Returns the value of the QML root element property specified by name.
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().
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(Object listener) |
You can use this property to provide code that is called after the QML file has been loaded.
Set the listener to an implementation of QmlInitializedListener
, for example:
felgoFragment.setQmlInitializedListener(new FelgoAndroidView.QmlInitializedListener() { @Override public void onQmlInitialized() { Log.d("Felgo Examples", "QML initialized!"); } });
void setQmlProperty(String name, Object value) |
Sets the QML root element property specified by name.
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 context, var source) |
Sets the QML file to load. Call this method before adding the Fragment with FragmentManager. The context parameter refers to the android.content.Context
.
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().