QtJenny: 生成 C++ 代理类以访问 Android API
演示 QtJenny 的使用。

概述
本演示展示了QtJenny的使用,并利用它生成 C++ 代理类,以便从 C++ 代码访问 Android API。生成的 C++ 类用于该演示的用户界面应用程序,以执行调整音量和亮度、激活和关闭唤醒锁、发送通知和触发振动等操作。这些操作是 Qt 没有实现的 Android API 的一部分。
使用 QtJenny 生成 C++ 类,无需手动编写JNI代码。
工作原理
该演示包含两个不同的部分,一部分是 UI 应用程序,即使用 QtJenny 生成的代码的Qt Quick 项目(名为qtjenny_consumer ),另一部分是三个不同的 Gradle 项目(名为qtjenny_general 、qtjenny_callback 和qtjenny_baseclass )的组合,它们共同使用 QtJenny 处理代码生成。这三个 gradle 项目都包含用于 QtJenny 代码生成的类注释和Gradle 配置。
在qtjenny_consumer 项目的 CMake 配置过程中,通过在qtjenny_general 、qtjenny_callback 和qtjenny_baseclass gradle 项目中执行kaptReleaseKotlin gradle 任务,自动触发 QtJenny 代码生成。
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()运行qtjenny_consumer 项目可启动用户界面应用程序。
生成 C++ 头文件
运行 gradle 项目中的kaptReleaseKotlin 任务会触发注释处理器,处理GenerateCppCode.kt 中声明的注释。
qtjenny_general 的GenerateCppCode.kt 文件中的代码片段:
@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])在qtjenny_general 的情况下,注释处理器会生成 C++ 头文件到qtjenny_output 目录。这些 C++ 头文件包含访问qtjenny_consumer 中使用的 Android API 所需的 JNI 模板代码。
qtjenny_general 中的应用程序级build.gradle 脚本指定了 QtJenny 实现的kapt参数。这些参数在 QtJenny 编译器中进行解析,并在生成过程中使用。
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
qtjenny_general 负责生成 Java 类的封装器,以便构建 Java 对象并调用其中的方法。这些包装器封装了常用的方法调用,而对于回调,则使用 qtjenny_baseclass 和 qtjenny_callback。
qtjenny_baseclass
qtjenny_baseclass 有效地允许在 C++ 代码中扩展 Java 类 ContentObserver,使用基类生成和回调生成的组合。
qtjenny_callback
qtjenny_callback 可以有效地在 C++ 中实现 Java 接口。qtjenny_baseclass 类扩展也使用了这种机制。
为了实现一个接口,需要构建一个 Java 代理类,使用一个 InvocationHandler(调用处理程序)来执行对生成的 C++ 类层次结构的虚拟函数调用。
在扩展基类时,生成的扩展类会对生成的 C++ 类层次结构执行虚拟函数调用。
在Qt Quick 应用程序中使用生成的 C++ 头文件
qtjenny_consumer 是使用qtjenny_general 生成的 C++ 头文件的Qt Quick 应用程序。我们将生成的头文件包含在backend.h 文件中,并在backend.cpp 中使用它们访问各种 Android API。
应用程序的用户界面由一个Main.qml 文件组成,该文件通过Q_INVOKABLE 和Q_PROPERTY 宏连接到BackEnd 类。
用户界面包含以下控件和操作。
唤醒锁
您可以使用Switches 激活或停用全部或部分唤醒锁。这些开关会触发Backend 类的相应Q_INVOKABLE 函数,从而激活唤醒锁并设置唤醒锁状态文本,在用户界面上显示给用户。
if (checked) { myBackEnd.setFullWakeLock() if (partialWakeLock.checked) partialWakeLock.click() mainWindow.wakeLockStatus = "Full WakeLock active"
设置部分唤醒锁使用的是连接PowerManager.WakeLock Android API 的WakeLockProxy 类。设置完全唤醒锁则使用连接到Window Android API 的WindowProxy 。
震动
您可以使用BackEnd::vibrate() 函数触发振动,该函数使用VibrationEffectProxy 、VibratorManagerProxy 和VibratorProxy 类创建振动。
通知
发送通知由Backend 中的BackEnd::notfy() 函数处理,并使用NotificationManagerProxy 类。
在BackEnd::createNotification() 函数中初始化Backend 类时已经创建了通知。
调整亮度
使用用户界面中的亮度滑块调节亮度会触发Backend 类中的属性变化,该变化将在BackEnd::setBrightness() 函数中处理。在这里,可以使用SettingsProxy,SystemProxy,ContextProxy,LayoutParamsProxy 和WindowProxy 类调整系统亮度。
亮度滑块与系统亮度是动态同步的,因此如果系统亮度从应用程序外部发生变化,亮度滑块就会进行调整,以反映当前的系统亮度。
如果应用程序没有写入系统设置的权限,则会以ACTION_MANAGE_WRITE_SETTINGS 的意图启动Activity 。启动Activity 后,用户必须手动授予应用程序写入系统设置的权限。
调整音量
使用用户界面中的音量滑块调节音量会触发Backend 类中的属性变化,该变化将在BackEnd::setVolume() 函数中处理。在这里,系统音量将通过AudioManagerProxy 类进行调整。
音量滑块与系统音乐音量动态同步,因此,如果系统音乐音量从应用程序外部发生变化,音量滑块就会进行调整,以反映当前的系统音乐音量。
© 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.