From a36d3869b1c68074ed4349ec9b64da80df8d5e01 Mon Sep 17 00:00:00 2001 From: Arnie via Claude Date: Fri, 12 Jun 2026 18:22:51 +0200 Subject: [PATCH] =?UTF-8?q?refactor:=20rename=20dashboards=E2=86=92webview?= =?UTF-8?q?s,=20unique=20applicationId=20per=20flavor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each flavor gets applicationIdSuffix = "." so the Bravia getApplicationList API returns a distinct URI per webview, enabling Control4 to launch specific flavors independently. BREAKING CHANGE: applicationId changed from cz.c3c.webviewkiosk to cz.c3c.webviewkiosk. — uninstall old app before reinstalling. BuildConfig.DASHBOARD_URL renamed to WEBVIEW_URL. Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 17 +++++++------ README.md | 25 +++++++++++-------- app/build.gradle.kts | 13 +++++----- .../java/cz/c3c/webviewkiosk/MainActivity.kt | 4 +-- dashboards.yaml => webviews.yaml | 0 5 files changed, 32 insertions(+), 27 deletions(-) rename dashboards.yaml => webviews.yaml (100%) diff --git a/CLAUDE.md b/CLAUDE.md index 6bdc714..048bcc3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,7 +1,7 @@ # android-webview-kiosk -Android TV app: fullscreen WebView showing a configurable Grafana dashboard. -Multiple APK flavors built from `dashboards.yaml` (repo root) — one APK per entry. +Android TV app: fullscreen WebView kiosk. +Multiple APK flavors built from `webviews.yaml` (repo root) — one APK per entry. Runs on the living-room Sony Bravia KD-65XE9305 (Android 8.0, API 26; Android System WebView updates independently via Play Store — currently v138). Launched remotely through the Bravia REST IP-control API by Control4 @@ -40,17 +40,18 @@ replaces it before any gradle command runs. - Package/applicationId: `cz.c3c.webviewkiosk`; repo name keeps the `android-` prefix, the package can't (hyphens illegal). -- Dashboard URL + label configured in `dashboards.yaml` (repo root). Each - entry becomes a product flavor; `BuildConfig.DASHBOARD_URL` is injected - at build time. Changing a URL means editing the YAML, rebuilding, resideloading. - Intentional: keeps Control4 integration to a single parameterless launch call. +- Webview URL + label configured in `webviews.yaml` (repo root). Each + entry becomes a product flavor with `applicationIdSuffix = "."`; + `BuildConfig.WEBVIEW_URL` is injected at build time. Changing a URL means + editing the YAML, rebuilding, resideloading. Intentional: keeps Control4 + integration to a single parameterless launch call. - `signing/release.keystore` is committed on purpose (private repo, LAN-only kiosk) so every build is upgrade-compatible. Don't reuse the key. - minSdk 26 is a hard floor — the TV never gets newer Android. - `LEANBACK_LAUNCHER` category + `android:banner` are what make the app visible to the Bravia API's `getApplicationList`/`setActiveApp`. Don't remove either. -- App URI (from `getApplicationList`): - `com.sony.dtv.cz.c3c.webviewkiosk.cz.c3c.webviewkiosk.MainActivity` +- App URIs (from `getApplicationList`) are per-flavor, e.g. weather: + `com.sony.dtv.cz.c3c.webviewkiosk.weather.cz.c3c.webviewkiosk.weather.MainActivity` - `setActiveApp` alone wakes the TV from standby — no separate `setPowerStatus` call needed. Control4 driver can skip the wake step. diff --git a/README.md b/README.md index bdf8017..fc1f196 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # android-webview-kiosk -Fullscreen WebView kiosk for Android TV. Shows configurable Grafana dashboards -defined in `dashboards.yaml`. Target device: Sony Bravia KD-65XE9305 (Android 8.0). +Fullscreen WebView kiosk for Android TV. Shows configurable web pages +defined in `webviews.yaml`. Target device: Sony Bravia KD-65XE9305 (Android 8.0). Built for remote launch via the Bravia REST IP-control API, driven by Control4. -## Dashboards +## Webviews -Defined in `dashboards.yaml` at repo root: +Defined in `webviews.yaml` at repo root: ```yaml weather: @@ -18,7 +18,8 @@ house_condition: label: House Condition ``` -Each entry produces a separate APK. Names must be valid Gradle identifiers +Each entry produces a separate APK with a unique `applicationId` +(`cz.c3c.webviewkiosk.`). Names must be valid Gradle identifiers (letters, digits, underscores — no hyphens). ## Build @@ -38,9 +39,9 @@ APKs: `app/build/outputs/apk//release/-release.apk` 2. `adb connect :5555` 3. `adb install -r app/build/outputs/apk/weather/release/weather-release.apk` -Fresh install (removing old app first): +Fresh install (first time or changing applicationId): - adb uninstall cz.c3c.webviewkiosk + adb uninstall cz.c3c.webviewkiosk. adb install app/build/outputs/apk//release/-release.apk Upgrades: bump `versionCode` in `app/build.gradle.kts`, rebuild, reinstall @@ -51,15 +52,17 @@ with `-r`. Same committed keystore = no uninstall needed. TV prerequisite: IP control auth = "Normal and Pre-Shared Key", Remote start enabled (wake from deep standby). -App URI (from `getApplicationList`): -`com.sony.dtv.cz.c3c.webviewkiosk.cz.c3c.webviewkiosk.MainActivity` +Each webview flavor has its own URI — retrieve per-flavor URIs via +`getApplicationList`. Example for `weather` (`cz.c3c.webviewkiosk.weather`): + +`com.sony.dtv.cz.c3c.webviewkiosk.weather.cz.c3c.webviewkiosk.weather.MainActivity` **`setActiveApp` alone wakes the TV from standby** — no separate `setPowerStatus` call is needed. The Control4 driver can use a single call: curl -s -X POST http://$TV_IP/sony/appControl \ -H "X-Auth-PSK: $PSK" -H 'Content-Type: application/json' \ - -d '{"method":"setActiveApp","id":601,"version":"1.0","params":[{"uri":"com.sony.dtv.cz.c3c.webviewkiosk.cz.c3c.webviewkiosk.MainActivity"}]}' + -d '{"method":"setActiveApp","id":601,"version":"1.0","params":[{"uri":""}]}' If the TV is already on, `setActiveApp` brings the kiosk to the foreground. If in standby, it wakes and launches directly. @@ -74,6 +77,6 @@ For reference, the two-step sequence (if needed for other integrations): # 2. launch (~6 s from quick standby, up to ~30 s from deep eco standby) curl -s -X POST http://$TV_IP/sony/appControl \ -H "X-Auth-PSK: $PSK" -H 'Content-Type: application/json' \ - -d '{"method":"setActiveApp","id":601,"version":"1.0","params":[{"uri":"com.sony.dtv.cz.c3c.webviewkiosk.cz.c3c.webviewkiosk.MainActivity"}]}' + -d '{"method":"setActiveApp","id":601,"version":"1.0","params":[{"uri":""}]}' Control4: a DriverWorks driver issuing `setActiveApp` is a separate project. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d31f643..4ce75dd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -6,8 +6,8 @@ plugins { } @Suppress("UNCHECKED_CAST") -val dashboards: Map> = - Yaml().load(rootProject.file("dashboards.yaml").inputStream()) +val webviews: Map> = + Yaml().load(rootProject.file("webviews.yaml").inputStream()) android { namespace = "cz.c3c.webviewkiosk" @@ -41,13 +41,14 @@ android { } } - flavorDimensions += "dashboard" + flavorDimensions += "webview" productFlavors { - dashboards.forEach { (name, config) -> + webviews.forEach { (name, config) -> create(name) { - dimension = "dashboard" - buildConfigField("String", "DASHBOARD_URL", "\"${config["url"]}\"") + dimension = "webview" + applicationIdSuffix = ".$name" + buildConfigField("String", "WEBVIEW_URL", "\"${config["url"]}\"") resValue("string", "app_name", config["label"] ?: name) } } diff --git a/app/src/main/java/cz/c3c/webviewkiosk/MainActivity.kt b/app/src/main/java/cz/c3c/webviewkiosk/MainActivity.kt index c1fd85e..29df925 100644 --- a/app/src/main/java/cz/c3c/webviewkiosk/MainActivity.kt +++ b/app/src/main/java/cz/c3c/webviewkiosk/MainActivity.kt @@ -50,7 +50,7 @@ class MainActivity : Activity() { if (!request.isForMainFrame) return lastLoadFailed = true handler.postDelayed( - { view.loadUrl(BuildConfig.DASHBOARD_URL) }, + { view.loadUrl(BuildConfig.WEBVIEW_URL) }, backoff.nextDelayMs(), ) } @@ -58,7 +58,7 @@ class MainActivity : Activity() { setContentView(webView) hideSystemUi() - webView.loadUrl(BuildConfig.DASHBOARD_URL) + webView.loadUrl(BuildConfig.WEBVIEW_URL) } override fun onResume() { diff --git a/dashboards.yaml b/webviews.yaml similarity index 100% rename from dashboards.yaml rename to webviews.yaml