QtJenny: Android API にアクセスするための C++ プロキシ・クラスの生成
QtJenny の使い方を紹介するデモです。

概要
このデモではQtJenny の使い方を紹介し、QtJennyを使用して C++ プロキシ・クラスを生成し、C++ コードから Android API にアクセスします。生成された C++ クラスは、このデモの UI アプリケーションで使用され、音量や明るさの調整、ウェイクロックの有効化と無効化、通知の送信、バイブレーションのトリガーなどのアクションを実行します。これらのアクションは、Qtが実装していないAndroid APIの一部です。
QtJenny を使って C++ クラスを生成することで、JNIコードを手作業で書く必要がなくなります。
どのように動作するか
デモには 2 つの特徴的な部分があり、1 つは UI アプリケーション、つまり QtJenny によって生成されたコードを使用するqtjenny_consumer というQt Quick プロジェクトで、もう 1 つはqtjenny_general 、qtjenny_callback 、qtjenny_baseclass という 3 つの異なる Gradle プロジェクトを組み合わせて QtJenny を使用したコード生成を処理するものです。3つのgradleプロジェクトにはそれぞれ、QtJennyコード生成のためのクラスアノネーションとGradle 設定が含まれています。
QtJenny コード生成は、qtjenny_general 、qtjenny_callback 、qtjenny_baseclass の各 gradle プロジェクトでkaptReleaseKotlin gradle タスクを実行することで、qtjenny_consumer プロジェクトの CMake 設定中に自動的にトリガーされます。
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 プロジェクトを実行すると、UI アプリケーションが起動します。
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 クラスの拡張もこのメカニズムを使用しています。
インターフェースを実装するために、生成されたC++クラス階層への仮想関数呼び出しを実行するInvocationHandlerを使用して、Java Proxyクラスが構築されます。
基底クラスを拡張する場合は、生成された拡張クラスが、生成された C++ クラス階層への仮想関数呼び出しを実行します。
生成された C++ ヘッダーをQt Quick アプリケーションで使用する。
qtjenny_consumer は、qtjenny_general で生成された C++ ヘッダーを使用するQt Quick アプリケーションです。生成されたヘッダーをbackend.h ファイルにインクルードし、backend.cpp でさまざまな Android API にアクセスするために使用します。
アプリのUIは1つのMain.qml ファイルで構成され、Q_INVOKABLE とQ_PROPERTY マクロを使ってBackEnd クラスに接続されています。
UIには以下のコントロールとアクションが含まれています。
ウェイク・ロック
Switches を使って、完全ウェイクロックまたは部分ウェイクロックを有効化および無効化できます。これらのスイッチは、Backend クラスの対応するQ_INVOKABLE 関数をトリガーし、ウェイクロックを有効化し、UI でユーザーに表示されるウェイクロックステータステキストを設定します。
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 クラスを使用してバイブレーションを作成します。
通知
通知の送信は、NotificationManagerProxy クラスを使用して、Backend のBackEnd::notfy() 関数で処理されます。
通知はBackEnd::createNotification() 関数のBackend クラス初期化中にすでに作成されています。
明るさの調整
UIの明るさスライダーで明るさを調整すると、Backend クラスのプロパティ変更がトリガーされ、BackEnd::setBrightness() 関数で処理されます。そこでは、SettingsProxy 、SystemProxy 、ContextProxy 、LayoutParamsProxy 、WindowProxy クラスを使用してシステムの明るさが調整されます。
明るさスライダーはシステムの明るさと動的に同期しているので、アプリケーションの外からシステムの明るさが変更されると、明るさスライダーは現在のシステムの明るさを反映するように調整されます。
アプリケーションにシステム設定を書き込む権限がない場合、ACTION_MANAGE_WRITE_SETTINGS のインテントでActivity が開始されます。このActivity が開始された後、ユーザーは手動でアプリケーションにシステム設定の書き込み許可を与える必要があります。
音量の調整
UI のボリューム・スライダーで音量を調整すると、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.