diff --git a/tests/auto/qtquickview/CMakeLists.txt b/tests/auto/qtquickview/CMakeLists.txt
index 81b76a27f1..aeec982df8 100644
--- a/tests/auto/qtquickview/CMakeLists.txt
+++ b/tests/auto/qtquickview/CMakeLists.txt
@@ -1,2 +1,3 @@
add_subdirectory(basic)
add_subdirectory(signallistener)
+add_subdirectory(statuslistener)
diff --git a/tests/auto/qtquickview/statuslistener/CMakeLists.txt b/tests/auto/qtquickview/statuslistener/CMakeLists.txt
new file mode 100644
index 0000000000..3577d5e275
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.22)
+ project(tst_qtquickview_statuslistener LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+ find_package(Qt6 REQUIRED COMPONENTS Quick)
+endif()
+
+qt_standard_project_setup()
+
+# Dummy test - just so this can be detected by ctest.
+# Actual test implementation is under ${CMAKE_CURRENT_SOURCE_DIR}/android/qml/
+# Add a source file, otherwise no test target is actually created.
+qt_internal_add_test(tst_qtquickview_statuslistener
+ SOURCES
+ empty.cpp
+)
+
+set_target_properties(tst_qtquickview_statuslistener
+ PROPERTIES
+ QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android
+)
diff --git a/tests/auto/qtquickview/statuslistener/android/AndroidManifest.xml b/tests/auto/qtquickview/statuslistener/android/AndroidManifest.xml
new file mode 100644
index 0000000000..bc5a92406b
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/AndroidManifest.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/auto/qtquickview/statuslistener/android/build.gradle b/tests/auto/qtquickview/statuslistener/android/build.gradle
new file mode 100644
index 0000000000..29391c9674
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/build.gradle
@@ -0,0 +1,67 @@
+plugins {
+ id 'com.android.application' version '8.3.0'
+ id 'org.qtproject.qt.gradleplugin' version '1.2'
+}
+
+def home = System.properties['user.home']
+def ndkPath = System.getenv('ANDROID_NDK_ROOT')
+QtBuild {
+ qtPath = file(home + '/work/install')
+ projectPath = file('qml/')
+ qtKitDir = file(home + '/work/install/target')
+ extraCMakeArguments = ['-DANDROID_NDK_ROOT=' + ndkPath]
+}
+
+android {
+ /*******************************************************
+ * The following variables:
+ * - androidBuildToolsVersion,
+ * - androidCompileSdkVersion
+ * - qtAndroidDir - holds the path to qt android files
+ * needed to build any Qt application
+ * on Android.
+ * - qtGradlePluginType - whether to build an app or a library
+ *
+ * are defined in gradle.properties file. This file is
+ * updated by QtCreator and androiddeployqt tools.
+ * Changing them manually might break the compilation!
+ *******************************************************/
+
+ namespace androidPackageName
+ compileSdkVersion androidCompileSdkVersion
+ buildToolsVersion androidBuildToolsVersion
+ ndkVersion androidNdkVersion
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = [qtAndroidDir + '/src', 'src', 'java']
+ res.srcDirs = [qtAndroidDir + '/res', 'res']
+ }
+ }
+
+ tasks.withType(JavaCompile) {
+ options.incremental = true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+
+ // Do not compress Qt binary resources file
+ aaptOptions {
+ noCompress 'rcc'
+ }
+
+ defaultConfig {
+ resConfig "en"
+ minSdkVersion qtMinSdkVersion
+ targetSdkVersion qtTargetSdkVersion
+ ndk.abiFilters = qtTargetAbiList.split(",")
+ }
+}
diff --git a/tests/auto/qtquickview/statuslistener/android/qml/CMakeLists.txt b/tests/auto/qtquickview/statuslistener/android/qml/CMakeLists.txt
new file mode 100644
index 0000000000..fd5ec46f72
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/qml/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.22)
+
+project(tst_qtquickview_statuslistener_qml LANGUAGES CXX)
+
+find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+find_package(Qt6 REQUIRED COMPONENTS Quick QuickTest QuickTestPrivate)
+
+qt_standard_project_setup()
+
+qt_add_executable(tst_qtquickview_statuslistener_qml
+ tst_qtquickview.cpp)
+
+set_source_files_properties(TestView.qml PROPERTIES QT_QML_GENERATE_JAVA_CLASS TRUE)
+set_source_files_properties(Invalid.qml PROPERTIES
+ QT_QML_SKIP_QMLDIR_ENTRY TRUE
+ QT_QML_SKIP_QMLLINT TRUE
+ QT_QML_SKIP_CACHEGEN TRUE)
+
+qt_add_qml_module(tst_qtquickview_statuslistener_qml
+ URI TestViewModule
+ VERSION 1.0
+ QML_FILES
+ Valid.qml
+ Invalid.qml
+ TestView.qml
+ SOURCES
+ testactivitycommunicator.h testactivitycommunicator.cpp
+)
+
+set_target_properties(tst_qtquickview_statuslistener_qml
+ PROPERTIES
+ QT_ANDROID_PACKAGE_NAME "org.qtproject.qt.android.tst_qtquickview_statuslistener_qml")
+
+target_link_libraries(tst_qtquickview_statuslistener_qml PRIVATE
+ Qt::Core Qt::Quick Qt::QuickTest Qt::QuickTestPrivate
+)
diff --git a/tests/auto/qtquickview/statuslistener/android/qml/Invalid.qml b/tests/auto/qtquickview/statuslistener/android/qml/Invalid.qml
new file mode 100644
index 0000000000..61e12178ee
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/qml/Invalid.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: root
+ Hello, this is some text in the middle of your otherwise nicely formed QML file.
+}
diff --git a/tests/auto/qtquickview/statuslistener/android/qml/TestView.qml b/tests/auto/qtquickview/statuslistener/android/qml/TestView.qml
new file mode 100644
index 0000000000..a34b8318c5
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/qml/TestView.qml
@@ -0,0 +1,45 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtTest
+
+Item {
+ id: root
+
+ TestActivityCommunicator {
+ id: communicator
+ }
+
+ SignalSpy {
+ id: qtQuickViewStatusSpy
+ target: communicator
+ signalName: "qtQuickViewStatusChanged"
+ }
+
+ TestCase {
+ id: validQmlFile
+ name: "Valid QML file"
+
+ function test_valid() {
+ qtQuickViewStatusSpy.clear()
+ communicator.loadQtQuickView("qrc:/TestViewModule/Valid.qml");
+ qtQuickViewStatusSpy.wait()
+ compare(qtQuickViewStatusSpy.count, 1)
+ compare(qtQuickViewStatusSpy.signalArguments[0][0], 1)
+ }
+ }
+
+ TestCase {
+ id: invalidQmlFile
+ name: "Invalid QML file"
+
+ function test_invalid() {
+ qtQuickViewStatusSpy.clear()
+ communicator.loadQtQuickView("qrc:/TestViewModule/Invalid.qml");
+ qtQuickViewStatusSpy.wait()
+ compare(qtQuickViewStatusSpy.count, 1)
+ compare(qtQuickViewStatusSpy.signalArguments[0][0], 3)
+ }
+ }
+}
diff --git a/tests/auto/qtquickview/statuslistener/android/qml/Valid.qml b/tests/auto/qtquickview/statuslistener/android/qml/Valid.qml
new file mode 100644
index 0000000000..bbd1e95e03
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/qml/Valid.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtTest
+
+Item {
+ id: root
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#00FF00"
+
+ Text {
+ anchors.centerIn: parent
+ text: "QML"
+ color: "black"
+ }
+ }
+}
diff --git a/tests/auto/qtquickview/statuslistener/android/qml/testactivitycommunicator.cpp b/tests/auto/qtquickview/statuslistener/android/qml/testactivitycommunicator.cpp
new file mode 100644
index 0000000000..b02fb40e70
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/qml/testactivitycommunicator.cpp
@@ -0,0 +1,39 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "testactivitycommunicator.h"
+
+using namespace QtJniTypes;
+
+static TestActivityCommunicator *s_instance;
+
+TestActivityCommunicator::TestActivityCommunicator(QObject *parent)
+ : QObject{ parent },
+ m_activity(TestActivity::callStaticMethod("instance"))
+{
+ s_instance = this;
+ TestActivity::registerNativeMethods({
+ Q_JNI_NATIVE_SCOPED_METHOD(jni_onQtQuickViewStatusChanged, TestActivityCommunicator)
+ });
+}
+
+TestActivityCommunicator::~TestActivityCommunicator()
+{
+ s_instance = nullptr;
+}
+
+TestActivityCommunicator *TestActivityCommunicator::instance()
+{
+ return s_instance;
+}
+
+void TestActivityCommunicator::loadQtQuickView(const QString &qmlUri)
+{
+ m_activity.callMethod("loadQtQuickView", qmlUri);
+}
+
+void TestActivityCommunicator::jni_onQtQuickViewStatusChanged(JNIEnv *, jclass, jint status)
+{
+ Q_ASSERT(s_instance);
+ emit s_instance->qtQuickViewStatusChanged(status);
+}
diff --git a/tests/auto/qtquickview/statuslistener/android/qml/testactivitycommunicator.h b/tests/auto/qtquickview/statuslistener/android/qml/testactivitycommunicator.h
new file mode 100644
index 0000000000..769a3b7604
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/qml/testactivitycommunicator.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TESTACTIVITYCOMMUNICATOR_H
+#define TESTACTIVITYCOMMUNICATOR_H
+
+#include
+#include
+#include
+
+Q_DECLARE_JNI_CLASS(TestActivity,
+ "org/qtproject/qt/android/qtquickview_statuslistener/TestActivity")
+
+class TestActivityCommunicator : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ explicit TestActivityCommunicator(QObject *parent = nullptr);
+ ~TestActivityCommunicator();
+
+ static TestActivityCommunicator *instance();
+
+public slots:
+ void loadQtQuickView(const QString &qmlUri);
+
+signals:
+ void qtQuickViewStatusChanged(int status);
+
+private:
+ QtJniTypes::TestActivity m_activity;
+
+ static void jni_onQtQuickViewStatusChanged(JNIEnv *, jclass, jint status);
+ Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_onQtQuickViewStatusChanged)
+};
+
+#endif // TESTACTIVITYCOMMUNICATOR_H
diff --git a/tests/auto/qtquickview/statuslistener/android/qml/tst_qtquickview.cpp b/tests/auto/qtquickview/statuslistener/android/qml/tst_qtquickview.cpp
new file mode 100644
index 0000000000..8f29983fb2
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/qml/tst_qtquickview.cpp
@@ -0,0 +1,6 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include
+
+QUICK_FOR_ANDROID_TEST_MAIN("tst_qtquickview_statuslistener")
diff --git a/tests/auto/qtquickview/statuslistener/android/res/layout/main.xml b/tests/auto/qtquickview/statuslistener/android/res/layout/main.xml
new file mode 100644
index 0000000000..6832617b66
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/res/layout/main.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/auto/qtquickview/statuslistener/android/settings.gradle b/tests/auto/qtquickview/statuslistener/android/settings.gradle
new file mode 100644
index 0000000000..a6b2c64381
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/settings.gradle
@@ -0,0 +1,15 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
diff --git a/tests/auto/qtquickview/statuslistener/android/src/org/qtproject/qt/android/qtquickview_statuslistener/TestActivity.java b/tests/auto/qtquickview/statuslistener/android/src/org/qtproject/qt/android/qtquickview_statuslistener/TestActivity.java
new file mode 100644
index 0000000000..69764f9603
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/android/src/org/qtproject/qt/android/qtquickview_statuslistener/TestActivity.java
@@ -0,0 +1,65 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+package org.qtproject.qt.android.qtquickview_statuslistener;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import org.qtproject.qt.android.QtQmlStatus;
+import org.qtproject.qt.android.QtQmlStatusChangeListener;
+import org.qtproject.qt.android.QtQuickView;
+import org.qtproject.qt.android.QtQuickViewContent;
+import org.qtproject.qt.android.tst_qtquickview_statuslistener_qml.TestViewModule.TestView;
+
+public class TestActivity extends Activity implements QtQmlStatusChangeListener
+{
+ native void jni_onQtQuickViewStatusChanged(int status);
+
+ private final TestView m_testView = new TestView();
+ private QtQuickView m_quickView;
+ private QtQuickView m_testingView;
+ private static TestActivity m_instance;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ m_instance = this;
+ m_quickView = new QtQuickView(this);
+
+ final FrameLayout qmlFrame = findViewById(R.id.qmlFrame);
+ final ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ qmlFrame.addView(m_quickView, params);
+ m_quickView.loadContent(m_testView);
+ }
+
+ public void loadQtQuickView(String qmlUri)
+ {
+ runOnUiThread(() -> {
+ FrameLayout parent = findViewById(R.id.qmlFrame2);
+ if (m_testingView != null)
+ parent.removeView(m_testingView);
+
+ m_testingView = new QtQuickView(this, qmlUri, "tst_qtquickview_statuslistener_qml");
+ m_testingView.setStatusChangeListener(new QtQmlStatusChangeListener() {
+ @Override
+ public void onStatusChanged(QtQmlStatus status) {
+ jni_onQtQuickViewStatusChanged(status.ordinal());
+ }
+ });
+ parent.addView(m_testingView,
+ new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ });
+ }
+
+ public TestView testView() { return m_testView; }
+
+ public static TestActivity instance() { return m_instance; }
+}
diff --git a/tests/auto/qtquickview/statuslistener/empty.cpp b/tests/auto/qtquickview/statuslistener/empty.cpp
new file mode 100644
index 0000000000..b8a0b724c2
--- /dev/null
+++ b/tests/auto/qtquickview/statuslistener/empty.cpp
@@ -0,0 +1,4 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+// Left empty on purpose.