From be0f2d7d371b5801f60248ad22617abeaa0f5a62 Mon Sep 17 00:00:00 2001 From: goon-foss Date: Thu, 17 Sep 2026 10:59:19 +0200 Subject: [PATCH] feat(android): apka instaluje sie i chodzi na Android TV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prosba z apki 2026-09-16 („make a tv app of this"). Tania wersja: to samo APK, zeby dalo sie je zainstalowac, znalezc w launcherze telewizora i obslugiwac pilotem w istniejacym interfejsie. Pelnego interfejsu 10-stopowego (podswietlenie fokusu, wieksze napisy, obejscie WebView przy hosterach) to NIE daje. - uses-feature leanback i touchscreen jako NIEwymagane, plus jawne screen.portrait=false: blokada pionu sama z siebie dokladala WYMAGANIE ekranu pionowego i telewizor uznawal apke za niezgodna - osobne wejscie TvMainActivity z LEANBACK_LAUNCHER, bez blokady pionu (na telefonie nic sie nie zmienia, launcher TV pyta tylko o leanback) - banner 320x180 w res/drawable (res/drawable-*/ jest w .gitignore) Dwie slepe uliczki, stad osobna klasa: `setRequestedOrientation` w onCreate to zmiana konfiguracji, wiec system relaunchowal aktywnosc i na TV zostawal bialy ekran (widok Reacta nie wracal); orientacja z values-television nie przechodzi, bo manifest czyta zasoby bez konfiguracji (lint ManifestResource). Sprawdzone na emulatorze android-34 android-tv (1920x1080): apka jest na liscie leanback launchera, startuje na caly ekran poziomo, a pilotem da sie przejsc bramke wieku (fokus chodzi po elementach, CENTER zaznacza), pominac samouczek i przewijac siatke scen. Odtwarzania na TV nie testowalem, emulator ma software'owe kodeki. Wersji APK nie ruszam, zmiana pojedzie z najblizszym wydaniem. Co-Authored-By: Claude Opus 5 --- .../android/app/src/main/AndroidManifest.xml | 23 ++++++++++++++++-- .../main/java/com/goon/mobile/MainActivity.kt | 3 ++- .../java/com/goon/mobile/TvMainActivity.kt | 19 +++++++++++++++ .../app/src/main/res/drawable/tv_banner.png | Bin 0 -> 7524 bytes 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 mobile/android/app/src/main/java/com/goon/mobile/TvMainActivity.kt create mode 100644 mobile/android/app/src/main/res/drawable/tv_banner.png diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index f289b99..d242d61 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,16 @@ + + + + + @@ -14,7 +24,7 @@ - + - + @@ -51,5 +61,14 @@ + + + + + + + \ No newline at end of file diff --git a/mobile/android/app/src/main/java/com/goon/mobile/MainActivity.kt b/mobile/android/app/src/main/java/com/goon/mobile/MainActivity.kt index b27e53a..1585701 100644 --- a/mobile/android/app/src/main/java/com/goon/mobile/MainActivity.kt +++ b/mobile/android/app/src/main/java/com/goon/mobile/MainActivity.kt @@ -13,7 +13,8 @@ import com.reactnative.googlecast.api.RNGCCastContext import expo.modules.ReactActivityDelegateWrapper -class MainActivity : ReactActivity() { +// open, bo dziedziczy z niej TvMainActivity (to samo, tylko bez blokady pionu). +open class MainActivity : ReactActivity() { override fun onCreate(savedInstanceState: Bundle?) { // Set the theme to AppTheme BEFORE onCreate to support // coloring the background, status bar, and navigation bar. diff --git a/mobile/android/app/src/main/java/com/goon/mobile/TvMainActivity.kt b/mobile/android/app/src/main/java/com/goon/mobile/TvMainActivity.kt new file mode 100644 index 0000000..6b37da3 --- /dev/null +++ b/mobile/android/app/src/main/java/com/goon/mobile/TvMainActivity.kt @@ -0,0 +1,19 @@ +package com.goon.mobile + +/** + * Wejscie dla Android TV. Ta sama aktywnosc co na telefonie, rozni sie WYLACZNIE wpisem + * w manifescie: telefon ma blokade pionu, telewizor jej nie ma, bo ekran telewizora jest + * na stale poziomy i pionowa aplikacja wychodzi tam waskim paskiem na srodku. + * + * Dlaczego osobna klasa, a nie jedna aktywnosc: + * - `setRequestedOrientation` w `onCreate` to zmiana konfiguracji, wiec system + * relaunchuje aktywnosc tuz po starcie i na TV zostawal bialy ekran (widok Reacta nie + * wracal; emulator android-34 android-tv, 2026-09-17), + * - orientacja z zasobu (`values-television`) nie przechodzi, bo manifest czyta zasoby + * bez kontekstu konfiguracji (lint ManifestResource), + * - `activity-alias` nie pozwala nadpisac `screenOrientation`. + * + * Telewizorowy launcher pyta o `LEANBACK_LAUNCHER`, wiec na telefonie ta klasa jest + * niewidoczna, a na TV widoczna jest tylko ona. + */ +class TvMainActivity : MainActivity() diff --git a/mobile/android/app/src/main/res/drawable/tv_banner.png b/mobile/android/app/src/main/res/drawable/tv_banner.png new file mode 100644 index 0000000000000000000000000000000000000000..334fb9d8b18d15b14f05f19db07cd7bd92986ec7 GIT binary patch literal 7524 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 literal 0 HcmV?d00001