# iMedia TV+ / Xtream Google TV Player (Hermes Edition) ## Spécifications, architecture et guide du projet **Projet :** Lecteur IPTV Xtream pour Google TV / Android TV **Package Android :** `ma.tkgraph.xtreamtv` **Plateforme cible :** Google TV / Android TV **Langage :** Kotlin **Interface :** Jetpack Compose / Compose TV **Lecteur vidéo :** AndroidX Media3 ExoPlayer **API IPTV :** Xtream Codes compatible **Date du document :** 11/06/2026 **Version :** 2.0 (Hermes) --- ## 1. Objectif du projet Développer une application Google TV complète pour lire des contenus IPTV depuis un serveur Xtream, en mettant l'accent sur : - **Qualité logicielle** : tests, architecture propre, sécurité - **Expérience utilisateur** : navigation fluide, télécommande, réactivité - **Résilience** : gestion d'erreur, cache, fallbacks gracieux - **Maintenabilité** : documentation, historique, conventions Fonctionnalités couvertes : - Connexion à un serveur Xtream + mémorisation sécurisée des identifiants - Lecture Live TV avec EPG court - Guide TV global + Replay / Catch-up TV - VOD et Séries avec catalogues complets - Favoris persistants (Live, VOD, Séries) - Chaîne épinglée au démarrage - Navigation complète à la télécommande Google TV - Support multilingue (français, anglais, arabe) - Cache local EPG pour performances --- ## 2. Architecture ### 2.1. Diagramme de flux ```mermaid flowchart TB subgraph UI ["Couche UI (Compose TV)"] Login[LoginScreen] Home[HomeScreen] Player[PlayerScreen] Guide[ProgramGuideScreen] Replay[ReplayGuideScreen] Vod[VodScreen] Series[SeriesScreen] end subgraph ViewModel ["Couche ViewModel"] VM_Home[HomeViewModel] VM_Player[PlayerViewModel] VM_Vod[VodViewModel] VM_Series[SeriesViewModel] end subgraph Repository ["Couche Repository"] Repo_Auth[AuthRepository] Repo_Live[LiveRepository] Repo_Vod[VodRepository] Repo_Series[SeriesRepository] Repo_Epg[EpgRepository] end subgraph Data ["Couche Data"] API[XtreamApi
Retrofit] Cache[EpgCache
Room / SQLite] Storage[ConfigStorage
EncryptedSharedPreferences] end subgraph External ["Externe"] Xtream[Xtream Server] end Login --> VM_Home Home --> VM_Home Player --> VM_Player Guide --> VM_Player Replay --> VM_Player Vod --> VM_Vod Series --> VM_Series VM_Home --> Repo_Auth VM_Home --> Repo_Live VM_Home --> Repo_Epg VM_Player --> Repo_Live VM_Player --> Repo_Epg VM_Vod --> Repo_Vod VM_Series --> Repo_Series Repo_Auth --> Storage Repo_Live --> API Repo_Vod --> API Repo_Series --> API Repo_Epg --> API Repo_Epg --> Cache API --> Xtream Storage -.->|Fallback| API ``` ### 2.2. Flux de navigation ```mermaid flowchart LR Splash[Splash
iMedia TV+] --> Login[LoginScreen] Login --> Home[HomeScreen] Home -->|Live TV| LiveList[Liste Chaînes] Home -->|Guide TV| GuideScreen[Guide TV Global] Home -->|VOD| VodScreen[Catalogue VOD] Home -->|Séries| SeriesScreen[Catalogue Séries] LiveList --> Player[PlayerScreen] GuideScreen --> Player ReplayGuide --> Player VodScreen --> Player SeriesScreen --> Player Player -->|Retour 1| Overlay Player -->|Retour 2| PreviousScreen Home -->|Retour| ConfirmQuit{Confirmer?} ``` ### 2.3. Structure des dossiers ``` app/ └── src/ ├── main/ │ ├── AndroidManifest.xml │ ├── java/ma/tkgraph/xtreamtv/ │ │ ├── MainActivity.kt │ │ ├── data/ │ │ │ ├── model/ ← DTOs Xtream │ │ │ ├── network/ ← Retrofit API + interceptors │ │ │ ├── repository/ ← Live, VOD, Series, EPG, Auth │ │ │ └── storage/ ← EncryptedSharedPreferences │ │ ├── ui/ │ │ │ ├── components/ ← ChannelLogo, CategoryRow, etc. │ │ │ ├── screens/ ← Login, Home, Player, Guide, etc. │ │ │ └── theme/ ← Thème Material 3 │ │ └── util/ ← UrlBuilder, CategorySort, Extensions │ └── res/ │ ├── drawable/ ← launch_background.xml │ ├── drawable-nodpi/ ← iMedia TV+ splash PNG │ ├── mipmap-*/ ← icône app │ ├── values/ ← strings.xml (default = EN) │ ├── values-fr/ ← strings.xml (français) │ └── values-ar/ ← strings.xml (العربية) ├── test/ ← Tests unitaires (JUnit + MockK) └── androidTest/ ← Tests UI (Compose Test) ``` --- ## 3. Stack technique détaillée | Couche | Technologie | Justification | |--------|-------------|---------------| | Langage | Kotlin 2.x | Moderne, sûr, natif Android | | UI | Jetpack Compose + Compose TV (1.7+) | Déclaratif, natif TV | | Lecteur | AndroidX Media3 ExoPlayer 1.5+ | Standard Google, HLS/DASH/MP4 | | Réseau | Retrofit 2.11+ / OkHttp 4.12+ | Robuste, interceptable | | Images | Coil 3.x | Asynchrone, cache, fallback | | Cache EPG | Room 2.7+ (SQLite) | Performant, requêtes typées | | Stockage | EncryptedSharedPreferences + AES-256 | Sécurité des credentials | | Tests unitaires | JUnit 5 / MockK / Turbine | Kotlin-friendly, Flow test | | Tests UI | Compose UI Test + Espresso | Automatisation UI TV | | Logging | Timber | Structuré, tags, crash | | Crash reporting | Firebase Crashlytics | Monitoring production | --- ## 4. Environnement de développement | Composant | Valeur | |-----------|--------| | OS de développement | Windows 11 | | IDE | Android Studio (Ladybug+) | | Terminal | PowerShell | | Appareil cible | Google TV / Android TV 12+ (API 31+) | | Connexion | ADB Wi-Fi ou USB | | JDK | OpenJDK 21 (via Android Studio) | | SDK Android | API 36, Build-Tools 36.x | | Gradle | 9.1+ (wrapper) | ### 4.1. Variables d'environnement ```powershell $env:JAVA_HOME = "D:\Program Files\Android\Android Studio\jbr" $env:ANDROID_HOME = "$env:LOCALAPPDATA\Android\Sdk" $env:Path = "$env:JAVA_HOME\bin;$env:ANDROID_HOME\platform-tools;$env:ANDROID_HOME\cmdline-tools\latest\bin;D:\Tools\Gradle\gradle-9.1.0\bin;$env:Path" ``` ### 4.2. Compilation ```powershell cd "D:\07-Logiciels\12-IPTV Andoid TV HERMES" .\gradlew.bat clean --no-daemon .\gradlew.bat :app:assembleDebug --no-daemon ``` APK générée : `app\build\outputs\apk\debug\app-debug.apk` --- ## 5. Sécurité ### 5.1. Stockage des identifiants **Problème de la v1 :** identifiants stockés en clair dans `SharedPreferences`. **Solution Hermes :** `EncryptedSharedPreferences` avec AES-256 GCM. ```kotlin // data/storage/SecureStorage.kt val masterKey = MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val prefs = EncryptedSharedPreferences.create( context, "imedia_secure_prefs", masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) ``` ### 5.2. Règles de sécurité - Aucun log contenant `username`, `password` ou `server_url` - Timeout réseau configuré (15s connect, 30s read) - Validation côté client avant envoi : URL bien formée, champs non vides - Pas de stockage en cache HTTP des credentials - OkHttp interceptor pour masquer les auth dans les logs debug - Préparation au HTTPS (certificats, SSR) --- ## 6. Gestion d'erreurs ### 6.1. Stratégie générale | Scénario | Comportement | Message utilisateur | |----------|-------------|---------------------| | Réseau indisponible | Toast + fallback cache EPG | "Connexion impossible. Vérifiez votre réseau." | | Timeout API (15s) | Retry 1x, puis message | "Le serveur ne répond pas. Réessayez." | | Auth échouée | Effacer champs, focus sur login | "Identifiants incorrects ou serveur invalide." | | Flux vidéo mort | 503 overlay, retour menu | "Flux indisponible pour cette chaîne." | | EPG vide | Afficher "Aucun programme" | "Aucun programme trouvé pour cette chaîne." | | Données corrompues | Fallback valeurs par défaut | "Des données sont manquantes — certains affichages peuvent être incomplets." | ### 6.2. État UI avec sealed class ```kotlin sealed class UiState { object Idle : UiState() object Loading : UiState() data class Success(val data: T) : UiState() data class Error(val message: String, val retry: Boolean = true) : UiState() } ``` ### 6.3. Intercepteur réseau ```kotlin class ErrorInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() return try { val response = chain.proceed(request) if (!response.isSuccessful) { throw XtreamHttpException(response.code, response.message) } response } catch (e: SocketTimeoutException) { throw XtreamTimeoutException("Le serveur Xtream est injoignable") } catch (e: UnknownHostException) { throw XtreamNetworkException("Aucune connexion réseau") } } } ``` --- ## 7. Cache EPG ### 7.1. Problème Le guide TV global peut nécessiter des centaines d'appels API (1 par chaîne). Sans cache, l'écran est inutilisable. ### 7.2. Solution : Room (SQLite) ```kotlin @Entity(tableName = "epg_cache") data class EpgCacheEntry( @PrimaryKey val id: Long, val streamId: Int, val channelName: String, val title: String, val description: String?, val startTimestamp: Long, val endTimestamp: Long, val cachedAt: Long = System.currentTimeMillis() ) ``` ### 7.3. Politique de cache | Type | Durée | Invalidation | |------|-------|-------------| | EPG court (live) | 2 minutes | Rafraîchi au scroll | | EPG complet (guide) | 15 minutes | Pull-to-refresh manuel | | Catégories | 1 heure | Au lancement | | Listes chaînes | 5 minutes | Changement de catégorie | ### 7.4. Flux EPG ```mermaid flowchart TD A[Ouvre Guide TV] --> B{Cache valide?} B -->|Oui < 15min| C[Afficher depuis Room] B -->|Non| D[Requête API par chaîne] D --> E[Stocker dans Room] E --> C ``` --- ## 8. Tests ### 8.1. Tests unitaires (JUnit 5 + MockK) | Fichier | Test | Ce qu'on vérifie | |---------|------|------------------| | `AuthRepositoryTest.kt` | Connexion valide/invalide | Repository retourne `Success` ou `Error` | | `AuthRepositoryTest.kt` | Timeout réseau | Erreur lisible, pas de crash | | `EpgRepositoryTest.kt` | Cache hit/miss | Appel API si cache expiré, sinon données locales | | `CategorySortUtilsTest.kt` | Tri FR/AR/autres | Ordre exact des catégories | | `XtreamUrlBuilderTest.kt` | URLs Live/VOD/Series | Format correct de chaque URL | | `SecureStorageTest.kt` | Lecture/écriture chiffrée | Données diffférentes en clair vs stocké | | `PlayerViewModelTest.kt` | Zapping gauche/droite | Chaîne suivante/précédente correcte | | `FavoritesRepositoryTest.kt` | Ajout/suppression favoris | Persistance après redémarrage | ### 8.2. Tests UI (Compose UI Test) | Fichier | Test | |---------|------| | `LoginScreenTest.kt` | Remplissage formulaire → bouton actif | | `LoginScreenTest.kt` | Erreur → message d'erreur affiché | | `HomeScreenTest.kt` | Navigation entre catégories OK | | `HomeScreenTest.kt` | Favori accessible via télécommande | | `PlayerScreenTest.kt` | Overlay disparaît après 3s | ### 8.3. Lancer les tests ```powershell # Tests unitaires uniquement .\gradlew.bat test --no-daemon # Tests UI (appareil/émulateur connecté) .\gradlew.bat connectedAndroidTest --no-daemon # Les deux .\gradlew.bat test connectedAndroidTest --no-daemon ``` --- ## 9. Internationalisation (i18n) ### 9.1. Langues supportées | Langue | Dossier | Statut | |--------|---------|--------| | Anglais (défaut) | `values/` | ✅ Prévu | | Français | `values-fr/` | ✅ Prévu | | Arabe | `values-ar/` | ✅ Prévu (RTL) | ### 9.2. Exemple ```xml iMedia TV+ Live TV Connect Connection lost. Check your network. iMedia TV+ Direct TV Connexion Connexion perdue. Vérifiez votre réseau. iMedia TV+ البث المباشر اتصال انقطع الاتصال. تحقق من شبكتك. ``` --- ## 10. Logging et Monitoring ### 10.1. Timber ```kotlin // Application.kt class XtreamApplication : Application() { override fun onCreate() { super.onCreate() if (BuildConfig.DEBUG) { Timber.plant(Timber.DebugTree()) } else { Timber.plant(CrashReportingTree()) } } } ``` Règles : - `Timber.d` / `Timber.i` pour debug et infos - `Timber.w` pour anomalies non bloquantes - `Timber.e` pour erreurs utilisateur - **Jamais** de log de credentials, tokens, ou données sensibles ### 10.2. Crash reporting Firebase Crashlytics est prévu pour la version release : - Rapports de crash automatiques - Logs non-sensibles attachés aux rapports - Clés custom : écran actif, dernier état réseau --- ## 11. Roadmap ### Phase 1 — Fondations (immédiat) - [x] Structure du projet - [x] Stack technique définie - [ ] Connexion Xtream + SecureStorage - [ ] Live TV avec Media3 ### Phase 2 — Fonctionnalités cœur - [ ] Catégories + Favoris Live - [ ] EPG court + Replay - [ ] Guide TV global - [ ] VOD + Séries ### Phase 3 — Qualité - [ ] Tests unitaires (couverture > 70%) - [ ] Cache EPG (Room) - [ ] Gestion d'erreur complète - [ ] i18n (FR, EN, AR) ### Phase 4 — Production - [ ] Signing + ProGuard - [ ] Firebase Crashlytics - [ ] Bannière Android TV + icônes finales - [ ] Politique de confidentialité - [ ] Publication Play Store --- ## 12. Conclusion Cette version Hermes reprend l'excellente base de la v1 et y ajoute : 1. **🔐 Sécurité** : chiffrement AES-256 des credentials 2. **📦 Cache EPG** : Room SQLite pour des performances réelles 3. **🧪 Tests** : stratégie complète (unitaire + UI) 4. **🌍 i18n** : support FR/EN/AR 5. **📋 Gestion d'erreur** : sealed class + intercepteurs + messages lisibles 6. **📊 Monitoring** : Timber + Crashlytics 7. **📐 Architecture** : flux documentés en Mermaid Le logiciel fonctionnait déjà en v1. Cette version le rend fiable, sécurisé et prêt pour la production.