Qt for Android の仕組み

Qt が Android プラットフォームをどのようにサポートしているのか、その概要を知りたい開発者の方は、このページをご覧ください。

Qt アプリケーションの開始

ネイティブのAndroidアプリと同様に、Qt main ActivityのonCreate()は、アプリが開始され、Activityが作成されると、早い段階で呼び出されます。ここで、AndroidQt Platform Abstraction(QPA)の初期化のほとんどが行われます。最も重要な部分は次のとおりです:

  • Qt とメインアプリケーションのライブラリのロード。
  • レンダリングサーフェスとトップレベルレイアウトの初期化、および入力、表示、タッチハンドラなどのさまざまなリスナーの登録を行うデリゲートの初期化。

Qtライブラリをロードするとき、QtCore が最初にロードされる間にJavaVMがキャッシュされる。これはJNI_OnLoad()関数の下で行われ、System.load()コールを使ってライブラリがロードされるときに同期的に呼び出される。すべてのQtモジュールは、ネイティブJNIメソッドの登録など、モジュール固有の初期化を行うために、この関数の実装を持っているかもしれません。

すべての Qt モジュール ライブラリがロードされると、Qt は Android QPA プラグインとメイン アプリケーション ライブラリをロードします。トップレベルQtLayout レイアウトのコンテンツが膨張し終わると、Qt アプリケーションのmain() ハンドルの場所が特定され、呼び出されます。これで C++ Qt アプリケーションが起動し、通常はメイン・イベント・ループが開始します。

Android QPA

Android QPAは、Android(Java/Kotlin)側とネイティブQt(C++)側を接続する役割を果たします。QtからAndroidへの、またAndroidからQtへの、さまざまなイベントやシグナルの伝搬を処理します。その責任は、シグナル処理、タッチイベント、UI要素、レンダリングなど多岐にわたります。このレイヤーは、アプリの起動時の初期化や、アプリの終了時や破棄時のクリーンアップも担当します。

スレッド

Qt for Androidアプリでは、Qtには通常2つのスレッドがあります。1つ目はQtが起動するQtThread 。もう1つはAndroid UIスレッドです。

QtThread

このスレッドはQtアプリによって実装され、例えばライブラリをロードする前に最初に起動されます。このスレッドはqtMainLoopThread と呼ばれます。以下の処理はすべてこのスレッドで実行されます:

  • Qtライブラリのロード。
  • JNI_OnLoad()内で行われる処理。
  • ネイティブ・アプリケーションの起動。
  • main() の実行。

Android UIスレッド

Androidアプリと同様に、UIに影響を与える操作はUIスレッドで実行されることが期待されています。Qtは、UIで実行されることが期待される内部コールのために、フードの下でそれを行います。また、Qt は C++ コードからこのスレッドで操作を実行するための APIrunOnAndroidMainThread() を提供しています。このAPIを使用することで、Qtはアプリがアクティブな場合は呼び出しがスレッドに直接ポストされるタイミングを管理し、アプリが一時停止中またはバックグラウンドの場合はキューに入れられます。

アーキテクチャ

"An overview Qt for Android's Architecture"

Qt クラス

次のセクションでは、さまざまな Qt Android クラスとその機能、Qt アプリケーションでの役割について説明します。

パブリックJavaバインディング

これらのクラスは、アクティビティサービスアプリケーションのようなユーザー向けクラスの内部実装の詳細をラップするパブリッククラスです。これらのクラスは Qt Android アプリでデフォルトで使用され、Android マニフェスト ファイルで参照されます。ビルドシステムとデプロイツールは、ビルドにこれらのクラスを含めるようにします。

ユーザーはこれらのクラスを使用して、デフォルトの動作を変更または拡張できます。たとえば、onCreate() の下にユーザー定義のカスタム・ロジックを追加するには、以下を使用します:

public class MyActivity extends QtActivity
{
    @Override
    protected void onCreate(Bundle bundle)
    {
        // code before Qt is initialized
        super.onCreate(bundle);
        // code after Qt is initialized
    }
}

注: カスタムアクティビティまたはバインディングクラスを使用するには、AndroidManifest.xmlファイルを編集する必要があります。

テーマの設定

QtActivityを拡張する場合、setTheme()を使用して特定のAndroidテーマを設定できます。ただし、Qtはデフォルトでテーマを設定するため、親クラスのonCreate()を呼び出す前にテーマを設定する必要があります。例えば

@Override
protected void onCreate(Bundle bundle)
{
    setTheme(android.R.style.Theme_DeviceDefault_DayNight);
    super.onCreate(bundle);
}

Android 10 以降のデフォルトでは、Qt はテーマTheme_DeviceDefault_DayNight Style を設定し、それ以前のバージョンではTheme_Holo_Light Styleを設定します。

アプリケーションパラメータを追加する

Java/Kotlin からアプリケーションの(main()) 関数に渡される引数であるアプリケーションパラメータを追加するには、QtActivity を拡張した後で次のようにします:

@Override
protected void onCreate(Bundle bundle)
{
    appendApplicationParameters("--flag value");
    super.onCreate(bundle);
}

これは、CMake変数QT_ANDROID_APPLICATION_ARGUMENTSを直接使用するのと似ています。どちらの方法で渡されたパラメータも、区切り文字としてスペースまたはタブを使用できます。アプリケーションに渡されたパラメータの最終リストは、QProcess::splitCommand を使用して解析されます。

QtLoader による Qt ライブラリのロード

すべての Qt Android アプリは、ネイティブ Qt ライブラリまたはサードパーティ・ライブラリが、それらのモジュールから機能を呼び出す前に最初にロードされていることを確認する必要があります。ビルドシステムは、アプリケーションのlibs.xmlリソースファイルの下に、様々な Qt ライブラリの依存関係、QPA プラグイン、メインアプリライブラリ、サードパーティライブラリのリストを保持します。以下のセクションで説明する前提条件がすべて完了すると、System.load() を使用してライブラリがロードされます。

クラス・ローダー

クラス・ローダー・オブジェクトは、Qt ライブラリをロードしたりデリゲートを初期化したりする前に、QtLoader によって早い段階で設定されます。これは、クラス・ローダーがQJniObject 、Javaクラスを見つけるために使用され、QJniObject でJNIコールを行う際に必要となるためです。

環境変数とアプリケーション・パラメーターの設定

ライブラリをロードする前に、Qt は環境変数が Android マニフェストのメタデータとして渡され、設定されていることを確認する必要があります。このステップにより、マニフェストのメタデータとして設定された設定フラグに基づいて、いくつかのモジュールの初期化が可能になります。このメタデータの一部は、アプリケーションの起動時に渡されるアプリケーション パラメータ リストにも反映されます。

setActivity()、setContext()、および setService()。

様々なQtモジュールが、アクティビティや サービスのコンテキストを必要とする初期化作業をJava側から行う必要があるかもしれません。それらのモジュールは、アクティビティ、サービス、またはコンテキストをパラメータとして受け取る静的メソッドを実装します:

void setActivity(Activity activity)
{
    m_activity = activity;
    // Other logic
}

そして、QtLoader 、ネイティブ共有ライブラリをロードする直前に、ローダーの親コンテキストでこれらのメソッドを呼び出します。

Qt for AndroidがAndroidアクティビティのライフサイクルを処理する方法

Qt for Androidは、onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()といったAndroidアクティビティのライフサイクル・コールバックを直接処理するAPIを提供していません。その代わりに、これらの処理をユーザーのために裏で行います。動作の概要は以下のセクションで説明します。

注: これらのライフサイクル・イベントは、QGuiApplication::applicationStateChanged シグナルに変換されます。

コンテキストの処理

QAndroidApplication Androidシステムとの対話に不可欠なAndroidコンテキストを QJniObject 。このコンテキストは、アクティビティまたはサービスになります。アクティビティがある場合は、サービスの有無にかかわらず、最も最近開始されたアクティビティとなる。サービスしかない場合は、最近起動したサービスになります。

注意: Qt for Android は複数のアクティビティをサポートしていません。

コールバック

QtActivityBaseクラスは、Activityの様々な機能の実装の詳細をQt for Androidパッケージ内で非公開にするためのクラスです。このクラスはAndroidのライフサイクルとQtフレームワークの仲介役となり、AndroidのライフサイクルのコールバックをQtアプリケーションが応答できるシグナルや操作に変換します。

onCreate()

アクティビティが作成されると、QtActivityBaseはQt環境を初期化します。これには、Qt ライブラリのロード、QJniObject が使用するクラスローダのセットアップ、アプリのメタデータの解析、Qt アプリケーションの実行準備などが含まれます。アクティビティに固有の必要な初期化がすべて処理されるようにします。

onStart()

AndroidのActivity.OnStart()を呼び出します。

onResume()

アクティビティがフォアグラウンドに移動すると、QtActivityBaseはQtアプリケーションを再開します。一時停止していたプロセスや操作が継続され、アプリケーションが再びユーザーとのインタラクションに対応できるようになります。onPause()で停止したディスプレイマネージャリスナーを再登録します。

onPause()

他のアクティビティによってアクティビティが部分的に見えなくなった場合、QtActivityBase は Qt アプリケーションを一時停止します。アプリケーションがフォアグラウンドでない間、アプリケーションの状態を保存したり、不要なリソースを解放したりします。

onStop()

アクティビティが表示されなくなると、QtActivityBase は Qt アプリケーションを停止し、より大規模な状態の保存とリソースの解放を行い、アプリケーションを破棄する準備をします。

注意: QtThread はこの時点で中断されます。

onDestroy()

アクティビティが終了するか、システムによって破棄される場合、QtActivityBaseはQtアプリケーションに関連するすべてのリソースをクリーンアップします。これは、適切なシャットダウンと、必要なクリーンアップ処理の実行を保証します。

この統合により、QtActivityBase が複雑な Android ライフサイクルを管理するため、開発者は心配することなく Qt アプリケーションの開発に集中することができます。

スプラッシュ画面の管理

QAndroidApplication QtActivityBase は、アプリケーションの起動シーケンス(通常は onCreate() の後)に合わせて、スプラッシュ画面をフェード効果で隠すことができます。

Qt for Android の詳細

2021 Qt World Summit のビデオでは、Qt for Android の概要が紹介されています。

"YouTube動画にリンクしているアジェンダの写真"

©2024 The Qt Company Ltd. ここに含まれるドキュメントの著作権はそれぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。