Kanzi Android Service での開発

Kanzi Android Service を使用すると、デバイス上の複数のアプリケーションから同じ Kanzi Android framework (droidfw) インスタンスを使用できます。これは、1 つのアプリケーション内の Android サービスで Kanzi Android framework (droidfw) をホストし、Android の IPC メカニズムを使用してすべてのクライアントアプリケーションからそれを利用することで実現されます。

これにより、次の機能が利用可能になります。

  • Shared libraries。クライアントアプリケーション間で単一の Kanzi ライブラリセットを再利用することで、静的メモリの使用量を最適化します。

  • Shared runtime and resources。クライアントアプリケーション間で同じ Kanzi Engine とリソースを共有することで、ランタイムのメモリと GPU の使用量を最適化します。

  • Improved application startup time。Kanzi Engine とリソースをバックグラウンドで事前に読み込むことで、起動時間を短縮します。

  • Cross-application transition animations。共有の Kanzi リソースを使用して、異なるアプリケーション間のシームレスなトランジションアニメーションを実現します。

Kanzi Android Service の使用例については、Android Service の例 を参照してください。

注釈

Kanzi Android Service はエクスペリメンタル機能であり、皆様からのフィードバックは非常に重要です。フィードバックを送信するには、こちらの フィードバックフォーム を使用してください。

アーキテクチャの詳細

サービスのアーキテクチャ図

サービスホストアプリケーション

このアプリケーションは、kzservice ライブラリを通じて Kanzi Android Service をホストします。サービスは Kanzi Android framework (droidfw) の初期化を担い、それを通じて Kanzi ランタイムを初期化します。ホストアプリケーションには、すべての Kanzi アセット、Kanzi ネイティブライブラリ、および Kanzi Engine プラグインをバンドルします。

クライアントアプリケーション

これらは、サービスアプリケーションの Kanzi 機能を使用する、同じシステム上の任意の数のアプリケーションです。クライアントアプリケーションは、kzclient ライブラリのビュー型とコンポーザブル型を使用して Kanzi にアクセスします。

アプリケーション間のトランジションアニメーション

クライアントは、共有の Kanzi リソースを使用して異なるアプリケーション間のシームレスなトランジションアニメーションを実行するよう、サービスに要求できます。これは、サービスが他のすべてのアプリケーションの上に表示されるオーバーレイウィンドウを作成し、そこにトランジションアニメーションをレンダリングすることで機能します。アニメーションが完了すると、オーバーレイウィンドウは非表示になります。

アプリケーション間のトランジションアニメーションの例

はじめに

Package Manager が提供するアプリケーションテンプレートを使用して、Kanzi Android Service プロジェクトを作成できます。パッケージマネージャーのインストール を参照してください。

始める前に、環境が Kanzi Android Service の要件を満たしていることを確認してください。Kanzi Android Service を参照してください。

Kanzi Studio で Kanzi Android Service プロジェクトを作成するには、次の手順に従います。

  1. New Project ウィンドウで、Template を Kanzi Android Service based Application Template に設定します。

  2. Create をクリックします。

    Kanzi は、Kanzi Studio プロジェクトと 2 つの Android Studio アプリケーションプロジェクトを作成します。

    1. <MyProject>Applicationandroid_service ディレクトリにある MyProjectHost サービスホストアプリケーション。

    2. <MyProject>MyProjectClient ディレクトリにある MyProjectClient アプリケーション。

クライアント API の使用

これは、クライアントアプリケーションでサービスアプリケーション内の Kanzi Engine インスタンスを設定し、通信するために使用する API です。

ビュー型とコンポーザブル型

Kanzi コンテンツを XML レイアウトまたはコンポーザブルに追加できます。

XML レイアウトで SurfaceView ベースのレンダリングを行うには、次を追加します。

<com.rightware.kanzi.service.KanziServiceSurfaceView
    android:id="@+id/clientred"
    app:clientId="clientred"
    app:kzbPathList="clientred.kzb"
    app:startupPrefabUrl="kzb://clientred/StartupPrefab"
    app:serviceHostPackage="com.example.host"
    app:serviceIntentAction="com.example.host.action.LAUNCH_SERVICE"
    />

TextureView ベースのレンダリングを行うには、次を追加します。

<com.rightware.kanzi.service.KanziServiceTextureView
    android:id="@+id/clientred"
    app:clientId="clientred"
    app:kzbPathList="clientred.kzb"
    app:startupPrefabUrl="kzb://clientred/StartupPrefab"
    app:serviceHostPackage="com.example.host"
    app:serviceIntentAction="com.example.host.action.LAUNCH_SERVICE"
    />

SurfaceView ベースのビューと TextureView ベースのビューの違いについては、Kanzi ビューを追加する を参照してください。

またはコンポーザブルに次を追加します。

KanziServiceComposable(
    modifier = Modifier,
    request = Request(
        clientId = "clientblue",
        kzbPathList = "clientblue.kzb",
        startupPrefabUrl = "kzb://clientblue/StartupPrefab",
    ),
    serviceHostPackage = "com.example.host",
    serviceIntentAction = "com.example.host.action.LAUNCH_SERVICE"
)

KanziServiceComposable は KanziServiceSurfaceView をベースにしており、オプションのパラメータ transparency、focusableInTouchMode、listener も受け付けます。

ビュー型とコンポーザブル型は、次の XML アトリビュートを受け付けます。

アトリビュート (Attribute)

フォーマット (Format)

ディスクリプション (Description)

clientId

ストリング (String)

各クライアントが指定する必要がある一意の識別子。

kzbPathList

ストリング (String)

このクライアントにロードする .kzb ファイルまたは .kzb.cfg ファイルのカンマ区切りリスト。

startupPrefabUrl

ストリング (String)

クライアントのロード時にクライアントのサーフェスにインスタンス化されるプレハブの URL。

serviceHostPackage

ストリング (String)

Kanzi Android Service をホストするアプリケーションの Android パッケージ名。

serviceIntentAction

ストリング (String)

Kanzi Android Service がクライアントアプリケーションをサービスにバインドするために使用するインテントアクション。

clearColor

カラー (Color)

サーフェスをクリアするために使用される色。デフォルト: 0xff000000。

clearEnabled

Boolean

サーフェスのクリアを有効にします。デフォルト: false。

rotaryHandlingEnabled

Boolean

組み込みのロータリー入力処理を有効にします。設定すると、Kanzi はロータリー入力イベントを処理し、Kanzi のキーイベントに変換します。デフォルト: true。

transparency

Boolean

トランスパレンシーのサポートを有効にします。デフォルト: false。

serviceHostPackage と serviceIntentAction が、Service ホストアプリケーションのマニフェストファイルで宣言されている applicationId および Intent アクションと完全に一致していることを確認してください。

KanziServiceClientListener

KanziServiceClientListener は、クライアントのライフサイクルイベントに関する通知を受け取るためのインターフェイスです。すべてのコールバックにはデフォルトで空の実装があるため、必要なコールバックのみをオーバーライドすれば済みます。

コールバック

ディスクリプション (Description)

onServiceConnected(client)

Kanzi Android Service が接続され、クライアントが使用可能になったときに呼び出されます。

onAttachedToWindow(client)

クライアントビューがウィンドウにアタッチされたときに呼び出されます。

onDetachedFromWindow(client)

クライアントビューがウィンドウからデタッチされたときに呼び出されます。

onSurfaceCreated(surface)

レンダリングサーフェスが作成され、使用可能になったときに呼び出されます。

onSurfaceDestroyed(surface)

レンダリングサーフェスが破棄される直前に呼び出されます。

onSurfaceChanged(surface, width, height)

レンダリングサーフェスのサイズが変更されたときに呼び出されます。

ビューにリスナーを設定するには、次のようにします。

val kanziView = findViewById<KanziServiceSurfaceView>(R.id.clientred)
kanziView.listener = object : KanziServiceClientListener {
    override fun onServiceConnected(client: KanziServiceClient) {
        // Service is ready, interact with Kanzi
    }
}

注釈

リスナーは、サービス接続が確立される前、またはビューがウィンドウにアタッチされる前に設定する必要があります。サービスがすでに接続された後にリスナーを設定すると、コールバックを受け取れません。

データソースのセッター

ビューベースのアプリケーションでは、KanziServiceClient のリファレンスを次のように取得できます。

val clientX = findViewById(R.id.clientred) as KanziServiceClient

Compose ベースのアプリケーションでは次のように取得できます。

var kanziServiceClient: KanziServiceClient? by remember { mutableStateOf(null) }
KanziServiceComposable(
    ...
    listener = object : KanziServiceClientListener {
        override fun onServiceConnected(client: KanziServiceClient) {
            kanziServiceClient = client
        }
    },
)

このリファレンスを通じて、セッター pushDataInt、pushDataString、pushDataReal、および pushDataBoolean にアクセスできます。例:

kanziServiceClient?.pushDataInt(
    "kzb://launcher/Data Sources/Scene Data source",
    "MainMenuScene",
    MainMenuScenes.HOME.value
)

データソースの KZB URL、データオブジェクトへのパス、およびプッシュする値を指定する必要があります。

クライアントの手動デタッチ

デフォルトでは、アクティビティが停止しても、クライアントアプリケーションはサービスから明示的にデタッチしません。その結果、サービスは関連付けられた Kanzi Engine インスタンスの実行を続け、そのクライアントに割り当てられたリソースを保持し続けます。

明示的にデタッチするには、アクティビティのライフサイクルメソッド内で KanziServiceClient インスタンスの handleClientAttached と handleClientDetached を呼び出します。

override fun onStop() {
    super.onStop()
    kanziServiceClient?.handleClientDetached()
}

override fun onStart() {
    super.onStart()
    kanziServiceClient?.handleClientAttached()
}

注釈

手動デタッチはシームレストランジション機能と互換性がありません。アプリケーション間トランジションを使用している場合は、これらのメソッドを呼び出さないでください。

向きの変更を処理する

デバイスの向きが変わったら、Kanzi のレンダリングをそれに応じて更新できるように Kanzi Android Service に通知します。

kanziServiceClient?.handleOrientationChange(newOrientation)

newOrientation を、Android の Configuration から取得した新しいデバイスの向きの値に設定します。

可視性の変更の処理

クライアントビューの可視性が変わったら、レンダリングを最適化できるように Kanzi Android Service に通知します。

kanziServiceClient?.handleVisibilityChange(isVisible)

ビューが表示されている場合は isVisible を true に、表示されていない場合は false に設定します。

Service API の使用

これは、サービスホストアプリケーションで Kanzi Java API を通じて Kanzi Android framework (droidfw) を初期化および設定するために使用する API です。

KanziServiceRuntime は参照カウント方式のシングルトンで、KanziServiceRuntime.acquire(context) を呼び出して取得します。サービスが開始される前にランタイムを維持しておくには、返された Reference を Application サブクラスのメンバーとして保持します。最後の Reference が閉じられると、ランタイムはシャットダウンします。

  • Kanzi Engine Java プラグインを登録するには、KanziServiceRuntime を取得し、その domain を Kanzi Java API で使用します。例:

    private lateinit var runtimeRef: KanziServiceRuntime.Reference
    
    override fun onCreate() {
        super.onCreate()
        runtimeRef = KanziServiceRuntime.acquire(this)
        val domain = requireNotNull(runtimeRef.get().domain) {
            "KanziServiceRuntime.domain must not be null after acquire()"
        }
        domain.registerPlugin(MyJavaPlugin())
    }
    
  • KanziServiceViewAdapterListener を実装すると、サービスホストアプリケーションで、クライアントアプリケーションに関連付けられた KanziViewAdapter のステートの変化をリッスンできます。

    たとえば、設定したスタートアッププレハブからインスタンス化されたノードツリーにアクセスして変更するには、KanziServiceViewAdapterListener.onPrefabLoaded コールバックを使用します。

    override fun onCreate() {
        super.onCreate()
        KanziServiceRuntime.addViewAdapterListener(clientId, object : KanziServiceViewAdapterListener {
            override fun onAttachedToWindow(
                clientId: String,
                viewAdapter: KanziViewAdapter,
                domain: Domain
            ) {
                // Look up a child node starting from the root.
                val text = viewAdapter.root.lookupNode<TextBox2D>("#Text")
                // Set properties on a node.
                text.setProperty(TextBox2D.TextProperty, "Hello world!")
            }
        })
    }
    

クライアントプレハブのプリロード

サービスホストアプリケーションでクライアントプレハブをプリロードしておくと、クライアントアプリケーションの起動時に、プレハブの読み込みを待たずにすぐに Kanzi のコンテンツを利用できます。

クライアントプレハブをプリロードするには、Application サブクラスの onCreate メソッドで KanziServiceRuntime を取得し、preloadClientPrefab を呼び出します。

private lateinit var runtimeRef: KanziServiceRuntime.Reference

override fun onCreate() {
    super.onCreate()
    runtimeRef = KanziServiceRuntime.acquire(this)
    runtimeRef.get().preloadClientPrefab(
        "clientred",
        arrayOf("clientred.kzb"),
        "kzb://clientred/Prefabs/ClientRedPrefab"
    )
}

preloadClientPrefab は、指定した clientId の KanziViewAdapter を作成し、KZB ファイルを読み込んで、プレハブをインスタンス化します。

クライアントアプリケーションの設定は、プレハブをプリロードするかどうかにかかわらず同じです。プリロードが影響するのはクライアントの起動時間のみです。

注釈

プリロードされたコンテンツは、同じ clientId を持つ実際のクライアントが接続してその所有権を取得するまでメモリに残ります。ある clientId でクライアントが一度も接続しない場合、そのプリロードされたリソースはサービスが存続する間、割り当てられたままになります。

アプリケーション間のトランジションアニメーションの設定

アプリケーション間のトランジションアニメーションを使用すると、Kanzi プロジェクト内で異なる Android アプリケーション間を移動する際に、シームレスな視覚的トランジションを作成できます。

アプリケーション間のトランジションを設定するには:

  1. ソースアプリケーションとターゲットアプリケーションの Kanzi サービスビューを、次のように設定します。

    • 同じ Kanzi Android Service インスタンスと同じ clientId を使用する。

    • 両方のクライアントアプリケーションで同じタイプの Kanzi サービスビュー (たとえば KanziServiceSurfaceView) を使用する。

    • アクティビティ内でフルスクリーンのビューにする。

    • Kanzi Android framework (droidfw) のトランスパレンシーの要件を満たす。透明なビューの作成 を参照してください。

      • Kanzi サービスビューで、次のように設定します。

        • transparency を true に

        • clearEnabled を true に

        • clearColor を @android:color/transparent に

      • application.cfg を編集して、アルファビットを持つサーフェスを必要とするようにします。カラーフォーマット (Color format) を参照してください。

        SurfaceBitsAlpha = 8
        
      • Kanzi Studio で透明なコンテンツを表示するノードを選択し、Properties で Background Brush プロパティを < No Brush > に設定します。

  2. 次のパラメータを指定して startSeamlessTransition API を呼び出します。

    • clientId - Android アプリケーション間を移動するクライアント ID。

    • transitionDuration - Kanzi のコンテンツがオーバーレイに表示され続ける時間。

    • kanziTransition - Kanzi のステートを更新して視覚的トランジションを駆動するラムダ関数。

    • androidTransition - Android 側のアプリケーションのトランジションを開始するラムダ関数。

    • leftMargin - オーバーレイ内で Kanzi のコンテンツを配置するための左マージン (ピクセル単位、省略可能)。デフォルト: 0。

    • topMargin - オーバーレイ内で Kanzi のコンテンツを配置するための上マージン (ピクセル単位、省略可能)。デフォルト: 0。

    • rightMargin - オーバーレイ内で Kanzi のコンテンツを配置するための右マージン (ピクセル単位、省略可能)。デフォルト: 0。

    • bottomMargin - オーバーレイ内で Kanzi のコンテンツを配置するための下マージン (ピクセル単位、省略可能)。デフォルト: 0。

    // Start a seamless transition between applications.
    kanziServiceView?.startSeamlessTransition(
        clientId = "coverflow",
        transitionDuration = 2.seconds,
        kanziTransition = {
            // Update Kanzi state to drive the visual transition.
            kanziServiceView?.pushDataInt(
                "kzb://service/Data Sources/Data source",
                "State",
                1
            )
        },
        androidTransition = {
            // Launch the target application.
            val intent = Intent().apply {
                setClassName(
                    "com.example.clientred",
                    "com.example.clientred.MainActivity"
                )
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }
            startActivity(intent)
        }
    )
    

    この API を呼び出すと、Kanzi Android Service はアプリケーションのトランジション中にアニメーションを表示するオーバーレイウィンドウを作成します。

  3. トランジションに関わる各アプリケーションに Display over other applications (他のアプリの上に重ねて表示) 権限を付与します。

    この権限を付与するには:

    1. サービスホストアプリケーションとクライアントアプリケーションをデバイスにインストールします。

    2. トランジションに関わる各アプリケーションについて:

      1. デバイスの設定を開きます。

      2. Apps > <ApplicationName> > Permissions に移動します。

      3. Display over other applications 権限を有効にします。

    注釈

    Android Automotiveデバイスでは、新しくインストールしたアプリケーションに対して、Android UIから Display over other applications 権限を付与することはできません。

    代わりに、APKにプラットフォームキーで署名して、この権限を自動的に付与できます。

既知の問題

  1. 現在、サービスホストアプリケーションには、どのクライアントもアニメーション機能を使用していない場合でも、Display over other applications 権限が必要です。

関連項目

Kanzi アプリケーションをAndroid向けに開発する

Kanzi Android framework (droidfw) での開発

Kanzi application framework (appfw) を使用した Android 向け開発

Kanzi アプリケーションをAndroidにデプロイする

Kanzi を使用した Android アプリケーション開発のトラブルシューティング

Java と Kotlin を使用して