GUI アプリ作成例: Chromium を利用した Web ブラウザアプリ

GUI アプリ作成例: Chromium を利用した Web ブラウザアプリ

このページでは、Actcast で GUI を持つアプリケーションをどのように作るかを、Chromium を利用した Web ブラウザアプリを例に説明します。

概要

Actcast アプリとして、ディスプレイ上でユーザに情報を提示し、また、マウスやキーボードから入力を受け付けるような GUI を利用したアプリを作成することができます。 表示したい内容に応じて GUI ライブラリで独自に GUI を実装したり、既存の GUI ソフトウェアをそのままアプリで利用したりといった活用が可能です。

サンプルアプリ

GUI アプリの作例として、Chromium を利用した Web ブラウザアプリの作成方法を紹介します。 このアプリは、Actcast デバイスに接続したディスプレイへ Web ページを表示する用途を想定しています。

Chromium ベース GUI アプリの表示例

例えば、次のような用途で利用できます。

  • 現場のダッシュボードを常時表示する
  • 案内用画面やサイネージを表示する

実装例として、 actcast-app-examples リポジトリ に Chromium を利用したサンプルコードがあります。 以降、このサンプルアプリを題材に、アプリの仕様を踏まえつつ、Actcast アプリとしての構成方法と処理の流れを説明します。

サンプルコードは こちら

サンプルアプリの仕様

このページで作成するブラウザアプリは、Actcast デバイス上で指定した URL を表示する GUI アプリです。

アプリが持つ機能

  • 起動時に Act 設定で指定したデフォルト URL を開く
  • Act 設定から表示領域の切り替えができる
    • ウィンドウ領域全体の全画面表示
    • クライアント領域のみの全画面表示
  • キーボードやマウスによる入力を受けられる

設定値

この作例では、Act 設定として次の値を扱います。

設定項目 説明
default_url 起動時に表示する URL
kiosk_mode true の場合に クライアント領域のみ の全画面表示となる
keylayout 使用するキーボード配列。jp または us を想定し、入力が必要な場合に使う

動作条件

  • ディスプレイが接続されていること
  • キーボードやマウスを使う場合、事前に接続されていること
  • デバイスが設置されるネットワークから,表示する URL に到達できること
    • proxy が必要等の理由で何らかのブロックが行われていないこと

重要

Act 起動中のキーボードやマウスの hotplug には対応していません。 入力機器を利用する場合は、Act の起動前に接続しておく必要があります。

実際の作り方

アプリケーション構成

この作例では、ActcastOS 4 向けにアプリケーションを作成します。 ハードウェア構成は Raspberry Pi 4B を前提にします。

Actcast アプリケーションとして最低限必要になるファイルは次の通りです。

  • app/main
  • app/main.py
  • app/healthchecker
  • .actdk/setting.json
  • .actdk/dependencies.json
  • manifesto/bookworm.json
  • setting_schema.json

開発モードで動作確認する際は、act_settings.json も用意します。

ディレクトリ構成の例は以下のようになります。 各ファイルの作成や設定内容については、後述の「プロジェクトの初期化」と「アプリケーション設定」で説明します。

chromium-browser-app
├── app
│   ├── main
│   ├── main.py
│   └── healthchecker
├── manifesto
│   └── bookworm.json
├── .actdk
│   ├── dependencies.json
│   └── setting.json
└── setting_schema.json

actdk init で生成されるファイルの役割は プロジェクトディレクトリの構成 を参照してください。

アーキテクチャ図

この作例における Actcast、Actcast デバイス、ハードウェア、表示先 Web サーバの関係は次のようになります。

Chromium ベース GUI アプリのアーキテクチャ図

Actcast Agent は、Act 設定や manifesto の内容に基づいてアプリコンテナを起動します。 アプリコンテナ内では app/main が Chromium を起動し、Chromium が表示先 Web サーバへアクセスしてディスプレイへ画面を表示します。 キーボードやマウスを扱う場合は、manifestohid-input を宣言しておく必要があります。

プロジェクトの初期化

アプリケーション開発プロジェクト作成 プロジェクト作成 に従い、 Actcast への新規アプリケーション登録を行い、そこで発番されたアプリケーション ID を用いて初期化を行います。

mkdir chromium-browser-app
cd chromium-browser-app
actdk init -i <APP_ID> -s "Chromium browser app" chromium-browser-app

<APP_ID> は Actcast Web UI で発行されたアプリケーション ID に置き換えてください。

Actcast Web UI に表示されるアプリケーション ID の例

開発用デバイスを利用する場合は、開発モードを有効化したデバイスをリモートデバイスとして追加します。

詳細については 開発モードの Actcast デバイスのセットアップ を参照してください。

actdk remote add <IDENTIFIER_YOU_LIKE>@<DEVICE_IP>

アプリケーション設定

actdk init で生成された設定を、ブラウザアプリ向けに修正します。 この作例では ActcastOS 4 の raspberrypi-bookworm を対象にするため、.actdk/setting.json.actdk/dependencies.jsonsetting_schema.jsonmanifesto/bookworm.json を次のように設定します。

.actdk/setting.json

ActcastOS 4 のデバイスでビルド・実行するために、target_typesraspberrypi-bookworm にします。 actdk init 時に, app_server_id には、Actcast Web UI で発行されたアプリケーション ID の値が指定されています。

.actdk/setting.json
{
  "app_id": "chromium-browser-app",
  "app_server_id": 1390,
  "short_description": "Chromium browser app",
  "short_descriptions": {},
  "target_types": [
    "raspberrypi-bookworm"
  ]
}

target_types.actdk/dependencies.jsonmanifesto/*.json の内容と一致している必要があります。

.actdk/dependencies.json

Chromium など GUI を利用するアプリを作る際は, GUI アプリ用の base_image を指定します。 Chromium 本体は .actdk/dependencies.jsonapt / pip に直接記述してインストールします。 actdk init で生成されたカメラアプリ向けの依存設定は、この作例に必要な内容へ置き換えてください。

.actdk/dependencies.json
{
  "apt": [],
  "pip": [],
  "raspberrypi-bookworm": {
    "base_image": "idein/actcast-rpi-app-base:gui-bookworm-9",
    "apt": [
      "chromium",
      "python3"
    ],
    "pip": [
      "actfw-core"
    ]
  }
}

base_image は、アプリイメージをビルドするときの土台になる Docker イメージです。 ここでは raspberrypi-bookworm 向けに、Chromium など GUI アプリの実行環境を含む idein/actcast-rpi-app-base:gui-bookworm-9 を指定しています。 このイメージは Docker Hub の idein/actcast-rpi-app-base で公開されています。

トップレベルの aptpip は、すべての target type に共通で追加する依存パッケージを書く場所です。 この作例では raspberrypi-bookworm のみを対象にしているため、追加するパッケージは raspberrypi-bookworm 側の apt に記述しています。 ここでは、Chromium をインストールするため、 その apt パッケージ名である chromium を追加しています。 また、このページでは app/main から main.py を Python で実行するため、その実行に必要な python3 も追加しています。

setting_schema.json

アプリの Act 設定項目を setting_schema.json に定義します。 URL や表示モード、キーボード配列の各項目を以下のように定義し、Act の利用者が Act 設定 から変更できるようします。 setting_schema.json に記述できる項目の詳細は アプリケーションの各種スキーマsetting_schema.json を参照してください。

setting_schema.json
{
  "$schema": "https://actcast.io/schema/v8/setting_schema_schema.json",
  "type": "object",
  "properties": {
    "default_url": {
      "title": "default url",
      "description": "URL to open when Chromium starts",
      "type": "string",
      "default": "https://actcast.io"
    },
    "kiosk_mode": {
      "title": "kiosk mode",
      "description": "Launch Chromium in kiosk mode",
      "type": "boolean",
      "default": true
    },
    "keylayout": {
      "title": "keylayout",
      "description": "Keyboard layout used by the app",
      "type": "string",
      "enum": [
        "jp",
        "us"
      ],
      "default": "jp"
    }
  },
  "required": [
    "default_url",
    "kiosk_mode"
  ],
  "propertyOrder": [
    "default_url",
    "kiosk_mode",
    "keylayout"
  ]
}

ユーザが Actcast Web UI 上で設定した Act 設定内容 は、このスキーマに従った JSON ファイルとして Actcast アプリへ渡され、アプリケーションから参照できるようになります。 この作例では actfw_core.Application().get_settings() を使って設定を読み込み、値を Chromium の起動引数や環境変数に反映します。

manifesto/bookworm.json

GUI アプリでは、アプリが利用する入出力デバイスを manifesto に明記します。 actdk init で生成された manifesto/bookworm.json にはカメラアプリ向けの cameravideocoreframebuffer が含まれている場合があります。 この作例ではブラウザアプリ向けにそれらを置き換え、画面表示のために display を、入力を扱う場合のために hid-input を指定します。

manifesto/bookworm.json
{
  "version": 2,
  "target_type": "raspberrypi-bookworm",
  "boards": [
    "RSPi4B"
  ],
  "devices": [
    {
      "type": "display"
    },
    {
      "type": "hid-input",
      "required": false
    }
  ],
  "network_mode": "bridge",
  "syscalls": [
    "clone",
    "unshare"
  ]
}

ここでのポイントは次の通りです。

  • display
    • ディスプレイへ画面を表示するために必要です
  • hid-input
    • キーボードやマウスを扱う場合に必要です
    • この作例では入力デバイスなしでも動作できるため required: false としています
  • network_mode: "bridge"
    • Chromium から表示先 URL へ制限なくアクセスできるようにするために指定します
  • syscalls: ["clone", "unshare"]
    • Actcast のコンテナ環境では一部の syscall が制限されているため、Chromium の起動に必要な cloneunshare を明示的に許可しています。

接続先 URL の制限について、必要に応じて network_mode やネットワークマニフェストも設定してください。 network_mode の詳細は アプリケーションの各種スキーマ を、ネットワークマニフェストの書き方は ネットワークマニフェスト を参照してください。

main ファイル

この作例では、Actcast アプリのエントリポイントとして app/main を用意し、実際の処理は app/main.py に記述します。

app/main

app/main
#!/usr/bin/env bash

exec python3 main.py

app/main.py

main.py では、Act 設定を読み込み、その内容に応じて Chromium の起動引数と環境変数を組み立てます。 また、Chromium の実行中は actfw_core.heartbeat() を呼び出して、アプリケーションの正常動作を Actcast に通知します。

処理の流れは次の通りです。

  1. actfw_core.Application().get_settings() で Act 設定を読み込む
  2. default_urlkiosk_mode から Chromium の起動引数を組み立てる
  3. keylayout の値から KEYLAYOUT などの環境変数を組み立てる
  4. actfw_core.task.Isolated を使って Chromium を起動し、実行中は heartbeat を送信し続ける
app/main.py
#!/usr/bin/python3
import os
import subprocess
import time
import actfw_core
from actfw_core.task import Isolated


def load_settings(app):
    settings = app.get_settings(
        {
            "default_url": "https://actcast.io",
            "kiosk_mode": True,
            "keylayout": "jp",
        }
    )

    return settings


def build_env(settings):
    # bashの export KEYLAYOUT / KEYMODEL を再現する
    env = os.environ.copy()
    env["KEYLAYOUT"] = settings["keylayout"]
    if settings["keylayout"] == "us":
        env["KEYMODEL"] = "pc105"
    return env


def build_chromium_command(settings):
    cmd = [
        "/usr/local/bin/start-x.sh",
        "chromium",
        "--no-first-run",
        "--disable-session-crashed-bubble",
        "--disable-infobars",
        "--no-default-browser-check",
    ]
    if settings["kiosk_mode"]:
        cmd.append("--kiosk")
    cmd.append(settings["default_url"])
    return cmd


class Chromium(Isolated):
    """Chromiumを起動するタスク"""

    def __init__(self, cmd, env):
        super().__init__()
        self.cmd = cmd
        self.env = env

    def run(self):
        proc = subprocess.Popen(
            self.cmd,
            env=self.env,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
        )

        while self.running:
            if proc.poll() is None:
                actfw_core.heartbeat()
            else:
                break

            time.sleep(1)

        proc.terminate()


def main():
    app = actfw_core.Application()
    settings = load_settings(app)

    env = build_env(settings)
    cmd = build_chromium_command(settings)

    app.register_task(Chromium(cmd, env))
    app.run()


if __name__ == "__main__":
    main()

default_urlkiosk_mode は Chromium の起動引数に直接反映しています。 keylayout は Chromium 自体の引数ではなく環境変数として設定し、/usr/local/bin/start-x.sh 経由で起動する Chromium の入力環境に反映しています。 /usr/local/bin/start-x.sh は、GUI 用ベースイメージに含まれるスクリプトで、ディスプレイ表示に必要な X 環境を起動し、その上で引数として渡した Chromium を実行します。

アプリケーションの死活監視

Actcast デバイスエージェントは、アプリケーションが不健全な状態にあると判断したとき、アプリケーションを再起動します。 アプリケーションの健全性の判定には healthchecker が利用されます。

以下は、healthchecker の実装例です。 /root/heartbeat ファイルの更新が 1 分以内に起きていることを確認するスクリプトとなっています。

app/healthchecker
#!/bin/bash

HEARTBEAT_FILE='/root/heartbeat'

[ "$(find "${HEARTBEAT_FILE}" -mmin -1)" = "${HEARTBEAT_FILE}" ]

healthchecker に対応するように、アプリケーション側では actfw_core.heartbeat() によって /root/heartbeat ファイルを一定間隔で更新します。 actfw_core.heartbeat() が呼び出されなくなると、healthchecker が失敗し、Actcast から異常を検知できるようになります。

アプリケーションのビルド

次のコマンドを実行することにより、Actcast アプリケーションをビルドします。

(開発版)

actdk build <IDENTIFIER_YOU_LIKE>

(リリース版)

actdk build --release

動作確認

まず、ディスプレイを接続した Raspberry Pi 4B を用意します。 入力も確認したい場合は、キーボードやマウスも接続してください。

次に、setting_schema.json に従った act_settings.json を作成します。 actdk generate act-settings を利用すると入力を補助できます。

actdk generate act-settings

act_settings.json の例:

act_settings.json
{
  "default_url": "https://actcast.io",
  "kiosk_mode": true,
  "keylayout": "jp"
}

ビルド後、開発用コンテナをデバイス上で起動します。

actdk debug container <IDENTIFIER_YOU_LIKE>

その後の接続方法やコンテナ内での確認手順は 開発モード を参照してください。 この Chromium アプリでは、実機のディスプレイにつないで URL が表示されること、kiosk_mode の有無で表示が変わること、必要ならキーボードやマウス入力が可能であることなどが動作確認項目となるでしょう。

確認が終わったら、次のコマンドでデバイス上の Act を停止します。

actdk stop <IDENTIFIER_YOU_LIKE>

Actcast へのアップロードとテスト

手元の Raspberry Pi 上で動作確認が取れたら、オンラインアップロードを行い、Actcast を経由してアプリを利用可能にします。 詳細は Actcast へのアップロードとテスト を参照してください。

オンラインビルドが完了したアプリケーションは、通常の Actcast アプリケーションと同様に Web UI から Act として Raspberry Pi にインストールし、動作を確認できます。

最終更新日