Code
Search code
Latest commit
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
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 standardandroid.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_WALLPAPERpermission.
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*inactivity_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/ keyhome_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.resourceConfigurationslimits the APK to the shipped languages. To add a language, copyvalues/strings.xmltovalues-<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
onStartandonStop, 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.

