TV App — une application pour téléviseurs intelligents fonctionnant sur les plateformes Apple TV (tvOS) et Android TV (Google TV). Contrairement aux applications mobiles, TV App est développée en tenant compte de la navigation par télécommande, de la gestion du focus (Focus Engine) et des exigences spécifiques de l'interface sur un grand écran. Le développement se fait en Swift/SwiftUI pour Apple TV et en Kotlin avec Leanback Library pour Android TV. Selon Statista (2026), plus de 250 millions d'appareils dans le monde fonctionnent sur ces plateformes, ce qui fait de TV App un créneau prometteur pour les développeurs. Examinons l'architecture des plateformes, la gestion du focus, des exemples de code et le processus de publication.
Points clés
TV App — une application conçue pour fonctionner sur les plateformes de téléviseurs intelligents : Apple TV (tvOS) et Android TV (Google TV). La principale différence avec une application mobile est la méthode d'interaction. L'utilisateur ne touche pas l'écran mais contrôle l'interface à l'aide d'une télécommande. Tous les éléments doivent être accessibles via une navigation directionnelle (D-pad) : haut, bas, gauche, droite et bouton de sélection.
Caractéristiques du développement TV App : la résolution d'écran varie du Full HD (1920x1080) au 4K (3840x2160) avec une densité xhdpi (Android) ou @3x (Apple). Une zone de sécurité de 5% des bords est obligatoire pour compenser le over-scan (une partie de l'image peut être coupée par le téléviseur). Il n'y a pas d'écran tactile — toutes les interactions se font via la télécommande ou la manette. Le focus met toujours en évidence l'élément actif. La consommation d'énergie n'est pas limitée par la batterie, mais l'application doit gérer correctement la transition en mode veille. Selon Statista (2026), le marché mondial des smart TV dépasse 80% des nouveaux téléviseurs, Apple TV et Android TV représentant plus de 250 millions d'appareils.
Catégories d'applications TV : services vidéo (Netflix, YouTube, Apple TV+), musique (Spotify, Apple Music), jeux (Apple Arcade, Google Play Games), fitness (Apple Fitness+, Peloton), éducation, actualités, météo, photos. La catégorie la plus populaire est le streaming vidéo, qui occupe 70% du temps d'utilisation total des smart TV.
tvOS est le système d'exploitation d'Apple pour le boîtier Apple TV, basé sur iOS. La première version remonte à 2015 avec l'Apple TV de 4e génération. tvOS partage avec iOS le noyau XNU, les frameworks Foundation, UIKit (dans une version adaptée) et le mécanisme de sécurité App Sandbox. Le développement se fait en Swift avec SwiftUI ou UIKit.
Composants principaux de tvOS :
Le cycle de vie d'une application tvOS est similaire à iOS : notRunning, foregroundActive, foregroundInactive, background. Particularité : l'application ne doit pas demander d'autorisations en arrière-plan inutilement — le système peut forcer l'arrêt d'un processus en arrière-plan. La topologie de navigation est construite autour de UISplitViewController et UITabBarController avec les onglets "Accueil", "Recherche", "Bibliothèque", "Paramètres".
Android TV est une version d'Android optimisée pour les téléviseurs et les boîtiers, présentée pour la première fois en 2014. Depuis 2020, Google TV existe — une surcouche d'Android TV avec une nouvelle interface, mais le développement d'applications se fait sur le SDK Android TV, compatible avec Google TV. Le langage principal est Kotlin, les frameworks d'interface sont Leanback Library (classique) et Jetpack Compose for TV (expérimental).
Composants clés d'Android TV :
Différences entre Android TV et Android mobile : l'application doit déclarer la catégorie LEANBACK_LAUNCHER dans le manifeste ; la largeur minimale de la mise en page est de 1920dp ; l'interaction tactile est remplacée par la navigation D-pad ; l'utilisation de fragments Leanback est recommandée ; l'accélération matérielle est obligatoire. La build inclut APK/AAB avec prise en charge des architectures ARM64 et x86. Pour les projets modernes à partir de 2025, Jetpack Compose for TV avec des composants TvLazyColumn, TvButton, TvCard est recommandé.
Focus Engine est un composant clé de toute plateforme TV, responsable de la détermination de l'élément d'interface actif. Sur tvOS, le Focus Engine est intégré à UIKit et fonctionne automatiquement. Lorsqu'un bouton du D-pad est pressé, le système analyse la position de tous les éléments focusables, calcule le candidat le plus proche dans la direction de la pression et déplace doucement le focus vers lui avec animation (UIFocusAnimationCoordinator).
Règles du Focus Engine : le système prend en compte la distance entre les éléments le long de l'axe de mouvement, l'intersection des projections des éléments (un élément est considéré comme candidat si sa projection intersecte la projection du focus actuel), la priorité des éléments à égale distance (le plus proche en ligne droite est sélectionné). Le développeur peut influencer le focus à l'aide de UIFocusGuide — un rectangle guide invisible qui redirige le focus vers un élément spécifique lors d'une pression dans une direction donnée.
Sur Android TV, le focus est implémenté via le système de focus standard d'Android avec les attributs focusable et nextFocus* (nextFocusDown, nextFocusUp, nextFocusLeft, nextFocusRight). L'animation est configurée via StateListAnimator. Google recommande de définir focusable sur tous les éléments interactifs et d'utiliser nextFocus pour un contrôle précis de la navigation. L'animation du focus est critique pour l'expérience utilisateur — lors du changement de focus, une animation d'échelle fluide (1.0 → 1.05–1.2) doit se produire avec une durée de 150–250 ms.
Exemple d'une application TV simple en SwiftUI pour Apple TV affichant une liste de films avec la prise en charge du Focus Engine.
import SwiftUI
struct Movie: Identifiable {
let id = UUID()
let title: String
let subtitle: String
}
struct ContentView: View {
@FocusState private var focusedMovie: UUID?
let movies: [Movie] = [
Movie(title: "Inception", subtitle: "2010, Sci-Fi"),
Movie(title: "Interstellar", subtitle: "2014, Sci-Fi"),
Movie(title: "The Matrix", subtitle: "1999, Action"),
Movie(title: "Blade Runner 2049", subtitle: "2017, Sci-Fi"),
]
var body: some View {
VStack(alignment: .leading, spacing: 40) {
Text("Films").font(.title).padding(.leading, 60)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 40) {
ForEach(movies) { movie in
VStack {
Image(systemName: "film.fill")
.resizable()
.frame(width: 200, height: 300)
.cornerRadius(12)
.focusable()
.focused($focusedMovie, equals: movie.id)
Text(movie.title).font(.headline)
Text(movie.subtitle).font(.subheadline).foregroundColor(.secondary)
}
.scaleEffect(focusedMovie == movie.id ? 1.15 : 1.0)
.animation(.easeInOut(duration: 0.2), value: focusedMovie)
}
}
.padding(.horizontal, 60)
}
}
.onAppear { focusedMovie = movies.first?.id }
}
}
Points clés : @FocusState — suivi du focus actuel ; .focusable() — rend un élément focusable ; .scaleEffect() — animation de zoom lors du focus, importante pour le retour visuel sur la TV.
Un exemple similaire pour Android TV avec Leanback Library en Kotlin :
// MainActivity.kt
class MainActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
class MainFragment : BrowseSupportFragment() {
private val moviePresenter = MoviePresenter()
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
title = getString(R.string.app_name)
headersState = HEADERS_ENABLED
setupAdapter()
}
private fun setupAdapter() {
val rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
val listRowAdapter = ArrayObjectAdapter(moviePresenter)
listRowAdapter.add(Movie("Inception", "2010", R.drawable.poster_1))
listRowAdapter.add(Movie("Interstellar", "2014", R.drawable.poster_2))
rowsAdapter.add(ListRow(HeaderItem(0, "Movies"), listRowAdapter))
adapter = rowsAdapter
}
}
data class Movie(val title: String, val subtitle: String, val imageResId: Int)
class MoviePresenter : Presenter() {
override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
val cardView = ImageCardView(parent.context).apply {
isFocusable = true
setMainImageDimensions(200, 300)
}
return ViewHolder(cardView)
}
override fun onBindViewHolder(viewHolder: ViewHolder, item: Any) {
val movie = item as Movie
(viewHolder.view as ImageCardView).apply {
titleText = movie.title
contentText = movie.subtitle
}
}
override fun onUnbindViewHolder(viewHolder: ViewHolder) {}
}
Points clés : BrowseSupportFragment — le fragment principal de Leanback avec en-têtes ; Presenter — une abstraction pour créer ViewHolder, similaire à RecyclerView.Adapter ; ImageCardView — carte standard avec image, titre et sous-titre ; isFocusable = true — attribut obligatoire pour les éléments TV.
Questions fréquentes
Une TV App est contrôlée par une télécommande (D-pad) au lieu du tactile, utilise Focus Engine pour la navigation, est optimisée pour un grand écran (Full HD ou 4K) et n'a pas de limitation de batterie. Tous les éléments doivent être accessibles par le mouvement directionnel du focus.
Le Focus Engine est un système sur tvOS qui détermine automatiquement l'élément d'interface actif. Lorsqu'un bouton du D-pad est pressé, le système analyse la position des éléments focusables, calcule le candidat le plus proche et déplace doucement le focus vers lui avec animation.
Le framework principal est Leanback Library (BrowseFragment, DetailsFragment, PlaybackOverlayFragment). Pour les projets modernes, Jetpack Compose for TV est également disponible avec un support expérimental.
Pour le développement initial, les simulateurs suffisent : Xcode inclut le simulateur tvOS avec Siri Remote, Android Studio inclut l'émulateur Android TV. Pour les tests finaux, un appareil physique est recommandé.
L'Apple TV App est publiée via App Store Connect avec Xcode Organizer. L'Android TV App est publiée via Google Play Console avec LEANBACK_LAUNCHER déclaré dans le manifeste et des captures d'écran 1920x1080.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi