QtJenny: Erzeugen von C++-Proxy-Klassen für den Zugriff auf Android-APIs
Demo, die die Verwendung von QtJenny demonstriert.

Überblick
Diese Demo zeigt die Verwendung von QtJenny und nutzt es, um C++ Proxy-Klassen zu generieren, um auf Android-APIs aus C++-Code zuzugreifen. Die generierten C++-Klassen werden in der UI-Anwendung dieser Demo verwendet, um Aktionen wie das Einstellen von Lautstärke und Helligkeit, das Aktivieren und Deaktivieren von Wecksperren, das Senden von Benachrichtigungen und das Auslösen von Vibrationen durchzuführen. Diese Aktionen sind Teil der Android-APIs, die Qt nicht implementiert.
Durch die Generierung von C++-Klassen mit QtJenny entfällt die Notwendigkeit, JNI-Code manuell zu schreiben.
Wie es funktioniert
Die Demo besteht aus zwei unterschiedlichen Teilen, einer ist die UI-Anwendung, d.h. das Qt Quick Projekt mit dem Namen qtjenny_consumer, das den von QtJenny generierten Code verwendet, und der andere ist eine Kombination aus drei verschiedenen Gradle-Projekten mit den Namen qtjenny_general, qtjenny_callback und qtjenny_baseclass, die zusammen die Codegenerierung mit QtJenny durchführen. Jedes der drei Gradle-Projekte enthält Klassenannonationen und Gradle Konfigurationen für die QtJenny-Codegenerierung.
Die QtJenny-Code-Generierung wird automatisch während der CMake-Konfiguration des Projekts qtjenny_consumer ausgelöst, indem der kaptReleaseKotlin gradle-Task in jedem der Projekte qtjenny_general, qtjenny_callback und qtjenny_baseclass gradle ausgeführt wird.
if (ANDROID)
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
set (gradlew_cmd "gradlew.bat")
else()
set (gradlew_cmd "./gradlew")
endif()
set (gradlew_arg "--rerun-tasks")
set (gradlew_task "kaptReleaseKotlin")
execute_process(COMMAND ${gradlew_cmd} ${gradlew_arg} ${gradlew_task}
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/qtjenny_baseclass")
execute_process(COMMAND ${gradlew_cmd} ${gradlew_arg} ${gradlew_task}
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/qtjenny_general")
execute_process(COMMAND ${gradlew_cmd} ${gradlew_arg} ${gradlew_task}
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/qtjenny_callback")
else()
message(FATAL_ERROR "Example only works on Android")
endif()Durch das Ausführen des qtjenny_consumer Projekts wird die UI-Anwendung gestartet.
Generierung der C++-Header
Das Ausführen der Aufgabe kaptReleaseKotlin in den gradle-Projekten löst einen Annotationsprozessor aus, der die in GenerateCppCode.kt deklarierten Annotationen verarbeitet.
Codeschnipsel aus der Datei GenerateCppCode.kt von qtjenny_general:
@NativeClass
@NativeProxy(allMethods = false, allFields = false)
@NativeProxyForClasses(namespace = "android::os", classes = [BatteryManager::class, VibratorManager::class,
Vibrator::class, VibrationEffect::class, Context::class, PowerManager::class, PowerManager.WakeLock::class,
Handler::class, Looper::class])
@NativeProxyForClasses(namespace = "android::view", classes = [Window::class, WindowManager.LayoutParams::class])
@NativeProxyForClasses(namespace = "android::media", classes = [AudioManager::class])
@NativeProxyForClasses(namespace = "android::drawable", classes = [android.R.drawable::class])
@NativeProxyForClasses(namespace = "android::app", classes = [Activity::class, Notification::class,
Notification.Builder::class, NotificationChannel::class, NotificationManager::class])
@NativeProxyForClasses(namespace = "android::provider", classes = [Settings.Global::class, Settings.System::class,
Settings::class])
@NativeProxyForClasses(namespace = "android::content", classes = [Intent::class, ContentResolver::class])Im Fall von qtjenny_general generiert der Annotationsprozessor die C++-Header im Verzeichnis qtjenny_output. Diese C++-Header enthalten den erforderlichen JNI-Boilerplate-Code für den Zugriff auf die in qtjenny_consumer verwendeten Android-APIs.
Das Skript auf App-Ebene build.gradle in qtjenny_general spezifiziert die Argumente für kapt, die QtJenny implementiert. Diese Argumente werden im QtJenny-Compiler geparst und im Generierungsprozess verwendet.
kapt {
arguments {
// pass arguments to jenny
arg("jenny.outputDirectory", project.file("../../qtjenny_output"))
arg("jenny.templateDirectory", project.file("../templates"))
arg("jenny.headerOnlyProxy", "true")
arg("jenny.useJniHelper", "false")
arg("jenny.useTemplates", "true")
}
}qtjenny_general
Die qtjenny_general kümmert sich um die Generierung von Wrappern für Java-Klassen, um die Konstruktion von Java-Objekten und den Aufruf von Methoden auf ihnen zu ermöglichen. Diese Wrapper verpacken die üblichen Methodenaufrufe, und für Callbacks werden die qtjenny_baseclass und qtjenny_callback verwendet.
qtjenny_baseclass
Die qtjenny_baseclass ermöglicht es, die Java-Klasse ContentObserver in C++-Code zu erweitern, indem eine Kombination aus Basisklassen- und Callback-Generierung verwendet wird.
qtjenny_callback
Die qtjenny_callback ermöglicht die Implementierung einer Java-Schnittstelle in C++. Die qtjenny_baseclass Klassenerweiterung nutzt ebenfalls diesen Mechanismus.
Um eine Schnittstelle zu implementieren, wird eine Java-Proxy-Klasse konstruiert, die einen InvocationHandler verwendet, der virtuelle Funktionsaufrufe in der generierten C++-Klassenhierarchie durchführt.
Zur Erweiterung einer Basisklasse führt die generierte erweiterte Klasse virtuelle Funktionsaufrufe in der generierten C++-Klassenhierarchie durch.
Verwendung der generierten C++-Header in der Anwendung Qt Quick
qtjenny_consumer ist die Anwendung Qt Quick, die die von qtjenny_general generierten C++-Header verwendet. Wir schließen die generierten Header in die Datei backend.h ein und verwenden sie in backend.cpp, um auf verschiedene Android-APIs zuzugreifen.
Die Benutzeroberfläche der Anwendung besteht aus einer Main.qml Datei, die über die Makros Q_INVOKABLE und Q_PROPERTY mit der Klasse BackEnd verbunden ist.
Die Benutzeroberfläche enthält die folgenden Steuerelemente und Aktionen.
Sperren aufwecken
Mit Switches können Sie entweder vollständige oder teilweise Wecksperren aktivieren und deaktivieren. Diese Schalter lösen entsprechende Q_INVOKABLE Funktionen der Klasse Backend aus, die die Wecksperre aktivieren und den Text für den Wecksperrstatus festlegen, der dem Benutzer in der Benutzeroberfläche angezeigt wird.
if (checked) { myBackEnd.setFullWakeLock() if (partialWakeLock.checked) partialWakeLock.click() mainWindow.wakeLockStatus = "Full WakeLock active"
Zum Einstellen der teilweisen Wecksperre wird die Klasse WakeLockProxy verwendet, die eine Verbindung zur Android-API PowerManager.WakeLock herstellt. Das Einstellen der vollständigen Aufwecksperre erfolgt mit WindowProxy, das mit Window Android API verbunden ist.
Vibrieren
Sie können eine Vibration auslösen, indem Sie die Funktion BackEnd::vibrate() verwenden, die die Klassen VibrationEffectProxy, VibratorManagerProxy und VibratorProxy verwendet, um die Vibration zu erzeugen.
Benachrichtigungen
Das Senden einer Benachrichtigung erfolgt über die Funktion BackEnd::notfy() in Backend unter Verwendung der Klasse NotificationManagerProxy.
Die Benachrichtigung wird bereits während der Initialisierung der Klasse Backend in der Funktion BackEnd::createNotification() erstellt.
Einstellen der Helligkeit
Die Einstellung der Helligkeit mit dem Helligkeitsregler in der Benutzeroberfläche löst eine Eigenschaftsänderung in der Klasse Backend aus, die in der Funktion BackEnd::setBrightness() behandelt wird. Dort wird die Systemhelligkeit mit Hilfe der Klassen SettingsProxy, SystemProxy, ContextProxy, LayoutParamsProxy und WindowProxy eingestellt.
Der Helligkeitsregler wird dynamisch mit der Systemhelligkeit synchronisiert. Wenn also die Systemhelligkeit von außerhalb der Anwendung geändert wird, passt sich der Helligkeitsregler an die aktuelle Systemhelligkeit an.
Wenn die Anwendung keine Berechtigung zum Schreiben von Systemeinstellungen hat, wird ein Activity mit der Absicht ACTION_MANAGE_WRITE_SETTINGS gestartet. Nach dem Start von Activity muss der Benutzer der Anwendung manuell die Berechtigung zum Schreiben der Systemeinstellungen erteilen.
Einstellen der Lautstärke
Die Einstellung der Lautstärke mit dem Lautstärkeregler in der Benutzeroberfläche löst eine Eigenschaftsänderung in der Klasse Backend aus, die in der Funktion BackEnd::setVolume() behandelt wird. Dort wird die Systemlautstärke mit Hilfe der Klasse AudioManagerProxy eingestellt.
Der Lautstärkeregler wird dynamisch mit der Systemmusiklautstärke synchronisiert, d. h. wenn die Systemmusiklautstärke von außerhalb der Anwendung geändert wird, passt sich der Lautstärkeregler an die aktuelle Systemmusiklautstärke an.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.