Skip to content

feat(tv): add Android TV / Fire TV wrapper and Roku channel - #1259

Merged
accius merged 9 commits into
accius:Stagingfrom
9M2PJU:feat/tv-apps
Nov 4, 2026
Merged

accius merged 9 commits into
accius:Stagingfrom
9M2PJU:feat/tv-apps

Conversation

@9M2PJU

@9M2PJU 9M2PJU commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

What

Puts OpenHamClock on the shack TV three ways:

  • Android TV / Google TV (android-tv/) — native Leanback WebView wrapper loading https://openhamclock.com full-screen. D-pad passthrough, Back = history then double-press exit, Menu reloads, offline retry screen, keep-screen-on, boot auto-start, official logo icon + 320x180 banner. Verified BUILD SUCCESSFUL + leanback-launchable badging.
  • Fire TV — same APK (Fire OS is Android; touchscreen/leanback marked not-required, both launcher categories declared). android-tv/install-firetv.sh installs over the network via adb; Downloader sideload also documented.
  • Roku (roku/) — Roku has no WebView, so this is a native SceneGraph channel using the hosted JSON API: map-lite world map (Natural Earth coastline, reproducible via images/render-map.py) with a runtime day/night terminator + sun marker, latest 20 DX spots, SFI/Kp/SSN strip, daytime N0NBH bands. package.sh builds a validated sideload zip (13 entries, XML-checked).

Verification

  • Android: cd android-tv && bash build.sh → BUILD SUCCESSFUL; aapt confirms leanback-launchable-activity + banner.
  • Roku: cd roku && bash package.sh → zip builds, both component XMLs parse, manifest/icons/splash present. BrightScript reviewed against SceneGraph API (Task-thread fetching, 1-based string indexing, no continue).
  • Base is freshly synced with upstream/Staging (merge 85c444a; one trivial scripts-block conflict in package.json resolved as union).

Notes for review

  • Debug package id is com.openhamclock.tv.debug; release is com.openhamclock.tv.
  • Roku channel polls the public hosted API every 60s — flag if you want longer intervals or a self-hosted default.
  • Happy to split Android vs Roku into separate PRs if preferred.

- android-tv/: native Leanback WebView wrapper loading
  https://openhamclock.com, D-pad navigation, offline retry screen,
  keep-screen-on, boot auto-start, official logo icon + banner,
  adb/network install script (install-firetv.sh covers Fire TV sticks)
- roku/: native SceneGraph channel (Roku has no WebView) rendering a
  TV dashboard from the hosted JSON API - map-lite world map with
  runtime day/night terminator, DX spots, SFI/Kp/SSN, N0NBH bands;
  package.sh produces a sideloadable zip
- .gitignore: local TV build outputs

@accius accius left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. Getting OpenHamClock onto the shack TV is a great idea, and the Android TV / Fire TV wrapper and the Roku channel are both very welcome. Before it can merge, though, the PR needs to shrink to just the TV apps: some files from your fork's own setup came along with it.

Please remove (fork-only, these would misbehave here):

  • .github/workflows/sync-upstream.yml, scripts/sync-upstream.sh and the sync:upstream npm script. In this repo, the workflow would add accius/openhamclock as its own upstream and push Staging and tags back to itself every night, with git identity 9M2PJU.

Please split into separate PRs (packaging needs its own discussion):

  • AUR: .github/workflows/update-aur.yml, aur/, scripts/update-aur.sh, the update:aur npm script. It pushes to aur.archlinux.org/openhamclock-git with commits authored as 9M2PJU, from an AUR_SSH_PRIVATE_KEY secret.
  • Snap: .github/workflows/publish-snap.yml, snap/, scripts/build-snap.sh, the build:snap npm script, docs/SNAP.md, and the Snapcraft lines in .gitignore. It would publish to the Snap Store on our release tags.
  • docs/PACKAGING.md, if it's about AUR/Snap.

Who owns and maintains those store listings and keys is a project decision, so let's talk about them on their own PRs or in an issue.

What stays here: android-tv/, roku/, the two README rows, and the Android/Roku .gitignore entries. Keep Android TV and Roku together or split them, whichever you prefer.

Two questions on the TV apps themselves:

  • Package id: releases use com.openhamclock.tv. Please don't publish to Google Play or the Amazon Appstore under that id yet; sideload builds are fine for now, and we'll sort out store accounts separately.
  • Roku polling: every 60 s against the hosted API is fine for the spots and solar data, but an optional self-hosted server URL would help people running their own install.

Thanks again, 73 de K0CJH

Remove fork-only sync workflow (sync-upstream.yml, scripts/sync-upstream.sh,
sync:upstream) and split AUR/Snap packaging out of this PR (update-aur.yml,
publish-snap.yml, aur/, snap/, scripts/update-aur.sh, scripts/build-snap.sh,
docs/PACKAGING.md, docs/SNAP.md + scripts). Packaging work is preserved on
feat/snap-package for separate PRs.

Keep only android-tv/, roku/, README rows, Android/Roku .gitignore entries.

Roku: add optional self-hosted serverUrl (OpenHamClock registry section,
trailing-slash tolerant, defaults to https://openhamclock.com) and document
it; status line shows effective host. Sideload-only, no store publishing.
@9M2PJU

9M2PJU commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review — and for welcoming the TV apps!

I've trimmed this PR to TV-only, per your notes:

  • Removed (fork-only): .github/workflows/sync-upstream.yml, scripts/sync-upstream.sh, and the sync:upstream npm script.
  • Removed from this PR (for separate packaging discussion): AUR (update-aur.yml, aur/, scripts/update-aur.sh, update:aur), Snap (publish-snap.yml, snap/, scripts/build-snap.sh, build:snap, docs/SNAP.md, Snapcraft .gitignore lines), and docs/PACKAGING.md. That work is preserved on my feat/snap-package branch, happy to open separate PRs/issues whenever you'd like to discuss ownership of the store listings and keys.
  • Kept: android-tv/, roku/, the two README rows, and the Android/Roku .gitignore entries. Diff vs upstream/Staging is now TV-only, and package.json is back to upstream.

On your two questions:

  • Package id: agreed — com.openhamclock.tv stays sideload-only for now, no Google Play / Amazon Appstore publishing. The README covers sideload via adb/Downloader only.
  • Roku polling: kept the 60s default, and added an optional self-hosted server URL — getServerBase() in components/MainScene.brs defaults to https://openhamclock.com with a registry override (OpenHamClock / serverUrl), documented in roku/README.md. Rebuilt the sideload zip to confirm (13 entries, both XMLs parse).

Thanks again — let me know if you'd like anything else adjusted. 73!

@accius accius left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick turnaround. The net diff is now just android-tv/, roku/, the two README rows and the TV .gitignore entries, and CI is green. Approving.

I went through the Android wrapper with an eye on WebView safety, and it's in good shape:

  • Certificate errors: onReceivedSslError cancels and shows the retry screen, so a bad certificate is never accepted.
  • Links: only http(s) stays in the WebView; other schemes go to the OS through a plain ACTION_VIEW, so intent:// links can't launch arbitrary components.
  • Everything else: no JavaScript bridge, file access off, cleartext off, and the boot receiver only listens for BOOT_COMPLETED.

Two small follow-ups, not blocking:

  • Roku: the registry override is a nice touch, but a user has no on-device way to write it. A one-screen "Server URL" option (or an ECP deep-link parameter such as serverUrl= on launch) would let self-hosters switch without repackaging.
  • Android TV: HOME_URL is fixed to openhamclock.com. A self-hosted option to match Roku would be welcome in a later PR.

Thanks also for keeping the Snap/AUR work on feat/snap-package. Open an issue when you're ready to talk about store ownership. 73 de K0CJH

@accius
accius merged commit 87ae583 into accius:Staging Nov 4, 2026
8 checks passed
@9M2PJU

9M2PJU commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the follow-ups — implemented both in #1268, sideload-only unchanged:

1. Roku — on-device Server URL + ECP deep-link

  • source/main.brs: main(args) accepts serverUrl= (falls back to URL in contentID), persists to OpenHamClock / serverUrl registry, passes to scene as serverUrl.
  • components/MainScene.xml: new serverUrl interface field.
  • components/MainScene.brs: precedence ECP field > registry > https://openhamclock.com, http(s):// validated, trailing / stripped. * (Options) opens a KeyboardDialog with Save / Reset to default / Cancel; empty + Save resets. Status line shows effective host + * = server hint.
  • E.g. curl "http://ROKU_IP:8060/launch/dev?serverUrl=http%3A%2F%2F192.168.1.10%3A3000"

2. Android TV — self-hosted to match Roku

  • MainActivity.java: DEFAULT_URL + SharedPreferences(ohc_tv/server_url). Precedence: --es serverUrl intent extra > saved pref > default, http(s):// validated, trailing / added.
  • On-device: Change server button on the offline screen, plus long-press MENU / INFO / GUIDE anytime (short-press still reloads via onKeyUp, startTracking + onKeyLongPress so hold doesn't reload first). Save persists, Reset clears to default.
  • adb shell am start -n com.openhamclock.tv/.MainActivity --es serverUrl http://192.168.1.10:3000 also works.
  • AndroidManifest.xml: usesCleartextTraffic="true" (only for user-configured LAN http; default stays https).

Verification

  • Android: cd android-tv && bash build.sh → BUILD SUCCESSFUL, aapt confirms leanback-launchable-activity + banner, package com.openhamclock.tv.debug.
  • Roku: cd roku && bash package.sh → 13-entry zip, both component XMLs parse.

Follow-up PR: #1268. Let me know if you want the dialog copy / key mapping adjusted. 73!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants