claude-code e4015e8a90 Treat JSON null city/country/date as absent
The overlay showed 'null, null' for photos without location because
JSONObject.optString returns the string "null" for JSON null.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012BvT3RjNpBmMUsyPqHq7fm
2026-09-11 21:38:15 +00:00
2026-09-11 16:26:31 +00:00
2026-09-11 16:26:31 +00:00
2026-09-11 16:26:31 +00:00
2026-09-11 16:26:31 +00:00
2026-09-11 20:00:25 +00:00

Immich Screensaver for Android TV

Ambient photo screensaver for Android TV / Google TV that plays photos and videos from your Immich server, in the spirit of the Google Photos ambient mode:

  • Full-screen slideshow with slow pan & zoom (Ken Burns), crossfade / slide / zoom transitions.
  • Portrait photos are shown two at a time, side by side.
  • Videos play inline (muted by default, capped length), lone portrait items sit on a blurred backdrop.
  • Date and location overlay, clock.
  • Works as the system screensaver (Settings → Screen saver) and as a normal app (start the slideshow manually).
  • Filter by albums, favorites, photos / videos.
  • Set up from your phone: the TV shows a QR code, the phone opens a form served by the TV on the LAN and sends the credentials; no typing with the remote.
  • Sign in with email + password once: the app creates a scoped API key (asset.read, asset.view, album.read, user.read) and never stores the password.

Tested against Immich 3.1. Requires Android 8.0+ (API 26).

Install

Grab app-release.apk from the releases page (or build it) and sideload it:

adb connect <tv-ip>
adb install -r app-release.apk

Optional: pre-configure the server without typing on the TV remote:

adb shell am start -n cloud.alexandrevazquez.immichtv/.ui.MainActivity \
  --es server https://immich.example.com --es api_key "$(pass show services/immich-api-key)"

Then on the TV: open Immich ScreensaverSet as system screensaver (or Settings → System → Screen saver) and pick it. Start slideshow now previews it; RIGHT / OK skips, BACK exits.

Build

export ANDROID_HOME=~/android-sdk
./gradlew assembleDebug            # app/build/outputs/apk/debug/app-debug.apk
./scripts/build-release.sh         # signed release, keystore password taken from pass

scripts/build-release.sh expects the keystore at ~/.android/immichtv-release.jks and its password in pass show android/immichtv-keystore-password.

Immich API used

Call Purpose
POST /api/search/random random batch of assets (albums / type / favorites filters, visibility: timeline)
GET /api/albums album picker
`GET /api/assets/{id}/thumbnail?size=preview fullsize
GET /api/assets/{id}/video/playback transcoded video stream
POST /api/auth/login + POST /api/api-keys one-time sign-in that mints the device key

Layout

  • data/ImmichApi.kt REST client (OkHttp + org.json).
  • data/SlideSource.kt endless shuffled stream of slides, portrait pairing, dedupe of recent assets.
  • ui/SlideshowView.kt rendering engine: layers, transitions, Ken Burns, ExoPlayer for video, overlays.
  • dream/ImmichDreamService.kt system screensaver entry point.
  • ui/SlideshowActivity.kt manual full-screen mode.
  • ui/MainActivity.kt + ui/SettingsFragment.kt Leanback settings UI.
S
Description
Salvapantallas Android TV con fotos y vídeos de Immich (estilo Google Photos ambient)
Readme 842 KiB
2026-09-12 06:26:52 +00:00
Languages
Kotlin 99.3%
Shell 0.7%