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

概要
このデモでは、QtJennyの使用例を紹介し、C++コードからAndroid APIにアクセスするためのC++プロキシクラスを生成します。 生成された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_consumer プロジェクトのCMake設定中に、qtjenny_general 、qtjenny_callback 、qtjenny_baseclass の各GradleプロジェクトでkaptReleaseKotlin というGradleタスクが実行されることで自動的にトリガーされます。
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 の場合、アノテーションプロセッサはqtjenny_output ディレクトリに C++ ヘッダーファイルを生成します。これらの 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プロキシクラスが構築されます。
基底クラスを継承する場合、生成された派生クラスは、生成されたC++クラス階層に対して仮想関数の呼び出しを行います。
Qt Quick アプリケーションで生成されたC++ヘッダーの使用
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 クラスを利用して振動を生成し、振動を発生させることができます。
通知
通知の送信は、Backend 内の `BackEnd::notfy() ` 関数において、`NotificationManagerProxy ` クラスを使用して処理されます。
通知は、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.