========================= Classroom digital signage ========================= :Author: Zhenyu Yang :Last updated: Feb 4, 2026 Overview ======== The ``signage/`` directory contains an Android “kiosk” app for classroom digital signage. The app runs in landscape mode, hides the system UI, and renders the signage UI using an embedded Android ``WebView``. At the moment, the UI is provided by a local HTML file packaged into the APK: - ``signage/app/src/main/assets/index.html`` (loaded via ``file:///android_asset/index.html``) There is also a more advanced UI mockup for reference/design work: - ``signage/signage_ui_example.html`` Repository layout ================= The signage app is a standalone Gradle project under ``signage/``: - ``signage/app/``: Android application module - ``signage/app/src/main/java/com/example/signage/MainActivity.kt``: kiosk activity hosting the WebView - ``signage/app/src/main/assets/index.html``: the shipped signage page (currently a static prototype) - ``signage/signage_ui_example.html``: UI mockup (not used by the app at runtime) How it works ============ On startup, ``MainActivity``: 1. Enables immersive full-screen mode (hides status/navigation bars). 2. Initializes a ``WebView`` with JavaScript and DOM storage enabled. 3. Loads the packaged HTML UI from Android assets. .. note:: - The app declares ``android.permission.INTERNET`` (so the HTML/JS can call remote APIs if needed), but the default configuration loads a local page. - The activity is locked to landscape mode via ``AndroidManifest.xml``. - ``onDestroy`` explicitly destroys the WebView to reduce the risk of memory leaks on low-memory devices. Backend API =========== Public endpoints for the kiosk UI: - ``GET /api/v1/signage/classrooms/{id}`` returns classroom signage fields. - ``GET /api/v1/signage/classrooms/{id}/schedule?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD`` returns course occurrences for the date range. The schedule endpoint is currently public (no authentication). Device authentication can be added later. Signage device fields (stored in a standalone signage table): - ``signage_enabled`` - ``signage_title`` - ``signage_subtitle`` - ``signage_config`` Building and running ==================== Prerequisites ------------- - Android Studio (recommended) or the Android SDK + command-line tools - A JDK compatible with your Android Gradle Plugin (AGP) version This project uses a Gradle Version Catalog (see ``signage/gradle/libs.versions.toml``). Build (Windows) --------------- From the repo root: .. code-block:: powershell cd signage .\\gradlew.bat :app:assembleDebug Build (Linux) ------------- From the repo root: .. code-block:: bash cd signage ./gradlew :app:assembleDebug .. note:: If you get a "Permission denied" error, run ``chmod +x ./gradlew`` first. The debug APK is typically generated under: ``signage/app/build/outputs/apk/debug/`` Install on a device ------------------- If you have ``adb`` available: .. code-block:: powershell adb install -r signage\\app\\build\\outputs\\apk\\debug\\app-debug.apk Customizing the signage UI ========================== The runtime page is the asset ``signage/app/src/main/assets/index.html``. You can: - Replace it with your own HTML/CSS/JS (keep the filename the same), or - Change the URL loaded in ``MainActivity`` to point to an ``https://`` endpoint. The current ``index.html`` is a static prototype (Chinese labels) and includes a “Check-in” button that calls a JavaScript object named ``CameraBridge`` if it exists: .. code-block:: javascript if (typeof CameraBridge !== 'undefined') { CameraBridge.startCapture(); } In this repository snapshot, a corresponding Android JavaScript bridge is not yet implemented. If you plan to support check-in or camera capture, you will need to: - Provide a Java/Kotlin object annotated with ``@JavascriptInterface`` and register it via ``WebView.addJavascriptInterface(...)``, and - Request and handle runtime camera permission and camera capture.