Public
Watch
1
Fork
You've already forked llauncher
0
0

Latest commit

maotovisk
a7cb329 2026-11-08 20:05:01 -03:00 3 commits
2026-11-08 19:44:16 -03:00
2026-11-08 19:44:16 -03:00
2026-11-08 19:44:16 -03:00
2026-11-08 19:44:16 -03:00

llauncher

A small Android TV launcher (dev.lveiga.llauncher), written in Kotlin with plain Android Views. It doesn't use Compose, image libraries or network access. It's built to replace the vendor launcher on the Unitv S1 (rk322x, Android 7.1.2) and should run on any Android TV / TV box from API 24 up.

Version 1.5 (versionCode 6)
minSdk / targetSdk / compileSdk 24 / 34 / 34
Download Releases (debug-signed APK, ~1.2 MB, with SHA-256)
Languages English (default), Português, Español

Screenshots

Home, 1.5 All apps

Screens

Home (MainActivity)

A minimal home page:

[ Settings ] [ Wi-Fi ] [ Bluetooth ] [ ▣ ]           weekday / date   HH:mm

[ main tile      ] [ fav 1 ] [ fav 2 ]
[                ] [ fav 3 ] [ fav 4 ]
[ fav 5 ] [ fav 6 ] [ fav 7 ] [ All apps ]
  • Main tile: one large tile for the app you use most.
  • 7 favorite slots, all set by hand. An empty slot shows "Add app" and opens the app picker.
  • All apps opens the full grid.
  • On first run the main tile and 4 favorites are filled in, preferring apps that have a TV banner. The rest stay empty on purpose. Camera and Settings are never seeded.
  • Until you edit the home screen for the first time, those defaults are recomputed from the current app list on every start. This repairs a slow first boot where Android had not finished scanning packages. The first edit freezes the layout.
  • Shortcuts open the TV Settings (com.android.tv.settings) screens: Settings → MainSettings, Wi-Fi → connectivity.NetworkActivity, Bluetooth → bluetooth.BluetoothActivity. If TV Settings isn't installed, the standard android.settings.* intents are used instead.
  • Hold OK or press Menu on a tile for: Change app, Remove from home, Move left/right/up/down (only directions that have a neighbouring slot are shown), App info.
  • Back does nothing, so the launcher never closes. Pressing HOME while already on the home screen moves focus back to the main tile.

Background

The small icon-only button after Bluetooth changes the wallpaper. There is no label on purpose.

  • Click: opens the system image picker (ACTION_GET_CONTENT, image/*) and sets the chosen picture as the system wallpaper. It is center-cropped to the screen and honours EXIF rotation. Files received with Send Files To TV land in Downloads, so a photo from a phone is two clicks away.
  • Hold OK: restores the built-in wallpaper.
  • Built-in wallpaper: pure black (so an OLED/AMOLED panel stays truly dark) with a blue gradient orb, a halo and a faint ambient glow. It is drawn from radial gradients in DefaultWallpaper.kt, so it costs no APK size and is sharp at any resolution. It is applied once, the first time the launcher runs.
  • TV boxes often ship no wallpaper chooser at all, so launcher does the decoding itself (WallpaperHelper.kt). Some boxes use a wallpaper surface larger than the screen (1920x1920 on the H96 Max); the helper hands the system a bitmap of exactly that size, with the picture in the centered band that is actually shown, so nothing is zoomed or shifted.
  • Needs only the normal SET_WALLPAPER permission.

All apps (AllAppsActivity)

A 5-column grid of every LAUNCHER / LEANBACK_LAUNCHER activity, sorted by label. It shows the TV banner when an app has one, otherwise the icon. Hold OK or press Menu for: Set as main app, Add to home (uses the first free slot), App info. Back returns to Home.

Design notes

  • The app list is loaded off the main thread on a single-thread executor, and reloads when apps are installed, removed or updated.
  • Banners and icons are drawn on a 2-thread pool into a process-wide LruCache (1/8 of the heap, at least 4 MB) shared by both screens.
  • D-pad focus on Home is wired explicitly with nextFocus* in activity_main.xml. The same neighbour map decides where Move up/down/left/right sends a tile. Focused tiles scale up and get an accent outline.
  • Home layout is saved as JSON in SharedPreferences llauncher_home / key home_v2. Slots that point to uninstalled apps show as empty.
  • Long-press is handled in dispatchKeyEvent (SelectLongPressHelper), so a remote that sends the long-press flag before the View long-click timer fires still opens the options menu.
  • Every user-visible string is in res/values*/strings.xml. resourceConfigurations limits the APK to the shipped languages. To add a language, copy values/strings.xml to values-<lang>/ and translate it. The clock and date use the system locale.

Source layout

app/src/main/java/dev/lveiga/llauncher/
  MainActivity.kt      home screen, slot actions, receivers
  AllAppsActivity.kt   full app grid
  HomeStore.kt         HomeConfig (hero + 7 favorites), seeding, JSON persistence
  HomeTileView.kt      home slot view (banner / icon / placeholder)
  AppAdapter.kt        All apps RecyclerView adapter
  AppRepository.kt     PackageManager queries
  IconLoader.kt        async artwork + LruCache (singleton)
  AppPickerDialog.kt   app chooser
  WallpaperHelper.kt   picks/crops/sets the system wallpaper
  DefaultWallpaper.kt  the built-in orb wallpaper, drawn from gradients
  TileActionDialog.kt  options menu
  QuickActionView.kt   header pill buttons
  SystemIntents.kt     TV Settings intents, app launch, localized date
  FocusUtils.kt        focus animation, long-press helper

Build

Requirements: JDK 17, Android SDK with platforms;android-34 and build-tools;34.0.0.

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
echo "sdk.dir=$HOME/Android/Sdk" > local.properties
./gradlew assembleDebug
# -> app/build/outputs/apk/debug/app-debug.apk

Toolchain used: Gradle 8.9 (wrapper), AGP 8.5.0, Kotlin 2.2.21. Dependencies: core-ktx, recyclerview, constraintlayout, cardview.

Install / make default

Download llauncher-debug.apk from the Releases page, check it against the published SHA-256, then:

adb install -r llauncher-debug.apk
adb shell cmd package set-home-activity dev.lveiga.llauncher/.MainActivity

In the clean ROM it's installed as a system app at /system/app/LLauncher/LLauncher.apk and is the only HOME activity.

Tested on device (Unitv S1, Android 7.1.2, 1280x720, pt-BR) — 2026-11-07

Check Result
Cold start as HOME, no crashes (AndroidRuntime:E empty) PASS
Portuguese strings, localized weekday/date PASS
D-pad map: header ↔ tiles, edges keep focus, grid paths PASS
Settings / Wi-Fi / Bluetooth open TV Settings activities PASS
All apps grid with banners and icon fallback, 15 apps PASS
Menu key and hold OK open options on Home and All apps PASS
Add to home from All apps fills first free slot PASS
Move down/left on a home tile follows on-screen position PASS
Change app via picker, Remove from home PASS
Persistence across force-stop and relaunch PASS
First-boot seeding with incomplete package list recovers on next load PASS
Seeded layout excludes Camera (no camera on TV boxes) PASS
Back on Home is ignored; Back on All apps returns home PASS

Screenshots: docs/screenshots/.

Changelog

  • 1.5: clean-memory button after the background icon, and double-press HOME on the launcher to kill background apps (killBackgroundProcesses, user apps only) and show the RAM freed.
  • 1.4: icon-only background button, built-in AMOLED orb wallpaper, glassy tiles, long-press OK on the icon restores it.
  • 1.3: fixes pinned apps showing as an empty "Add app" tile when the app was installed or updated while the launcher was in the background (package broadcasts are only received between onStart and onStop, so the app list is now re-queried on resume).
  • 1.2: tweaks for TV boxes; installed as a system app in the clean ROMs.
  • 1.1: initial public layout (main tile, 7 favorites, All apps).

Also verified on an H96 Max RK3318 (Android 9, 1920x1080) on 2026-11-08: the stale-list fix and the background picker.

Known limitations

  • Debug-signed. For distribution, build a release with your own key. In a system image the signature only matters for future updates.
  • Debug-signed builds all share the same debug key, so they update each other in place but are not a trust anchor.
  • Banner-less apps show a centered icon. There's no artwork fetched from the internet, by design.
  • One fixed layout (1 main + 7 favorites). It isn't configurable yet.
  • Hiding apps from All apps isn't supported.