15 KiB
Plugin plugins/google_cast – Guida pratica / Debug operativo
Questa guida è la versione pratica del documento di architettura del plugin google_cast.
L’obiettivo è aiutarti a capire rapidamente:
- quale parte del flusso è coinvolta
- quale file toccare
- dove guardare quando qualcosa non funziona
- come distinguere i problemi Google Cast standard dai problemi Custom Receiver
1. Mappa mentale rapida
Flusso generale
Flutter UI
↓
cast_controller.dart
↓
┌───────────────────────────────┬───────────────────────────────┐
│ GoogleCastController │ CustomCastController │
│ (Google Cast standard) │ (Custom Receiver CAF/web) │
└───────────────┬───────────────┴───────────────┬───────────────┘
↓ ↓
MethodChannel('google_cast') MethodChannel('google_cast')
↓ ↓
FlutterCastFrameworkPlugin.kt (Android)
↓
┌──────────────┬───────────────┬──────────────┬──────────────┐
│ Context │ Session │ MediaClient │ QueueManager │
│ Manager │ Handler │ │ │
└──────────────┴───────────────┴──────────────┴──────────────┘
↓
Google Cast framework / Receiver
2. File principali: a cosa servono in pratica
Lato Flutter / App
lib/widgets/cast/cast_controller.dart
È la facciata unificata.
Usalo per capire:
- quale backend è attivo (
google,custom,dlna) - dove finiscono i comandi UI
- come vengono sincronizzati i notifier condivisi:
- indice corrente
- stato play/pause
- posizione/durata
- volume/mute
Se hai un bug tipo:
- il pulsante UI chiama il backend sbagliato
- i notifier non si aggiornano
- la cast bar chiama il backend sbagliato
👉 il primo file da guardare è questo.
lib/widgets/cast/google_cast_controller.dart
È il cervello Dart del Google Cast standard.
Qui trovi:
- connessione del flusso Google Cast
- caricamento queue standard
- slideshow lato Flutter
- polling media/volume
- sync verso fullscreen viewer / controlli
Se hai un bug tipo:
- slideshow Google si ferma
- foto/video si comportano male
- seek cambia sulla TV ma non sul telefono
- volume non si aggiorna nella UI
onCastReadygenera comportamenti strani
👉 guarda questo file.
lib/widgets/cast/custom_cast_controller.dart
È il cervello Dart del Custom Receiver.
Qui trovi:
- avvio sessione/receiver custom
- invio messaggi JSON al receiver web
- polling custom (
MEDIA_STATUS,VOLUME_STATUS) - slideshow custom
- comandi
LOAD_QUEUE,NEXT,PLAY,PAUSE, ecc.
Se hai un bug tipo:
- Custom connect funziona ma la TV mostra male il contenuto
- overlay/progress duplicati
- volume custom non cambia davvero il video
- il receiver risponde ma Flutter non si aggiorna
👉 guarda questo file + il receiver web.
lib/widgets/collection/app_bar/cast/cast_icon_button.dart
Gestisce il tap sull’icona Cast nella app bar.
Qui si decide se il tap deve fare:
- solo connessione device
- oppure connessione + media
Se hai un bug tipo:
- scegli Google ma sembra partire Custom
- il cast parte subito quando scegli il device
- il device si connette ma la UX è sbagliata
👉 guarda questo file.
lib/widgets/collection/app_bar/cast/cast_bar_inline.dart
È la seconda barra orizzontale con:
- cast manuale
- fullscreen cast
- slideshow
- prev/next
- stop slideshow
- stop cast
Se hai un bug tipo:
- parte con gli item sbagliati
- usa una selezione vecchia
- startIndex invalido
- overflow orizzontale della barra
👉 guarda questo file.
lib/widgets/collection/app_bar/cast/cast_controls_sheet.dart
È il bottom sheet dei controlli.
Qui trovi:
- seek
- prev/play-pause/next
- volume/mute
- stop slideshow
- stop cast
Se hai un bug tipo:
- il volume non compare
- il volume compare ma non si aggiorna
- i controlli interagiscono col backend sbagliato
- la UI chiama
controller.google/controller.customdirettamente
👉 guarda questo file.
lib/widgets/viewer/fullscreen_cast_viewer.dart
È il viewer fullscreen locale sincronizzato col Cast.
Se hai un bug tipo:
- il video sulla TV cambia seek ma il telefono no
- il fullscreen non segue l’indice Cast
- il video locale e il Cast non sono allineati
👉 guarda questo file.
Lato plugin Android
plugins/google_cast/android/src/main/kotlin/com/aves/google_cast/FlutterCastFrameworkPlugin.kt
Router centrale del plugin.
Riceve tutto dal MethodChannel('google_cast').
Se hai un bug tipo:
- Flutter chiama un metodo ma sembra non arrivare al native
- un comando non viene instradato bene
- un handler non viene più registrato
👉 guarda questo file.
CastContextManager.kt
Gestisce:
CastContextActivity- sessione Cast corrente
RemoteMediaClient
Se hai un bug tipo:
- sessione non trovata
- device connesso ma client nullo
- callback non agganciata al client corretto
👉 guarda questo file.
CastSessionHandler.kt
Gestisce gli eventi di sessione:
onSessionStartedonSessionResumedonSessionEndedonCastReadyonCastStopped
Se hai un bug tipo:
- il device si connette ma Flutter non sa che è pronto
- la seconda barra non compare
- la sessione finisce ma Flutter resta “connected”
👉 guarda questo file.
CastDialogLauncher.kt
Mostra il dialog nativo di selezione device.
Se hai un bug tipo:
- l’icona Cast non apre il picker
- il picker si apre ma non seleziona device
👉 guarda questo file.
CastMediaClient.kt
Gestisce:
- play / pause / seek
- get media status
- volume / mute
- callback
RemoteMediaClient.Callback
Se hai un bug tipo:
onQueueIndexChangednon arriva più a FlutteronVideoFinishednon arrivaInvalid Request- volume nativo Google non si aggiorna
👉 guarda questo file.
CastQueueManager.kt
Gestisce:
loadQueue(items, startIndex)next()prev()- costruzione
MediaQueueItem - metadati (
index,isVideo, mime, title)
Se hai un bug tipo:
Invalid startIndex- queue rotta o item sbagliati
- Google Cast non va al prossimo item come dovrebbe
👉 guarda questo file.
CastCustomReceiver.kt
Gestisce l’avvio del custom receiver web/CAF.
Se hai un bug tipo:
- il receiver custom non parte
- parte ma non riceve messaggi
- la sessione custom sembra connettersi ma non carica nulla
👉 guarda questo file.
3. Mappa dei comandi principali
Comandi Flutter → plugin Android
Connessione
showCastDialogstartCustomReceiver
Queue / navigazione
loadQueuenextprev
Media
playpauseseekTogetMediaStatus
Volume
getVolumesetVolumesetMute
Stop
stopCast
4. Mappa degli eventi di ritorno
Google Cast standard → Flutter
onCastReadyonCastStoppedonQueueIndexChangedonVideoFinishedonCastError
Custom Receiver → Flutter
Di solito via messaggi custom, per esempio:
CAST_READYCAST_STOPPEDMEDIA_STATUSVOLUME_STATUS
5. Troubleshooting rapido
Problema: seleziono il device e subito compaiono
Invalid RequestMediaQueue error 2001IDLE_REASON_ERROR
Causa probabile
Il polling media parte troppo presto, cioè già su onCastReady quando non esiste ancora una queue/media caricata.
Dove guardare
google_cast_controller.dartCastMediaClient.kt
Fix tipico
- non avviare
startMediaPolling()dentroonCastReady - far partire il polling solo dopo
loadQueue - lato native, ignorare gli stati in cui
mediaInfo == null
Problema: slideshow Google fa prima e seconda foto, poi si ferma
Causa probabile
Flutter non riceve più il cambio item queue, quindi il timer slideshow non viene riarmato.
Dove guardare
google_cast_controller.dartCastMediaClient.kt- eventualmente
CastQueueManager.kt
Fix tipico
- ripristinare la callback
RemoteMediaClient.Callback - reinviare a Flutter
onQueueIndexChanged(index, isVideo) - in Dart riarmare il timer solo per le foto
Problema: in slideshow un video viene saltato dopo 5 secondi
Causa probabile
Il timer slideshow delle foto parte anche sui video.
Dove guardare
google_cast_controller.dartcustom_cast_controller.dart
Comportamento corretto
- foto → timer
- video → nessun timer, deve finire da solo e poi passare al successivo
Problema: in presentazione manuale/fullscreen le foto avanzano da sole
Causa probabile
La logica slideshow è rimasta attiva quando non dovrebbe.
Dove guardare
google_cast_controller.dartcustom_cast_controller.dartcast_bar_inline.dart
Comportamento corretto
- manuale/fullscreen: le foto restano ferme fino a un comando manuale
- i video invece vanno al successivo a fine riproduzione
Problema: Invalid startIndex: X
Causa probabile
Stai caricando una queue con un indice iniziale più grande della lunghezza della lista.
Dove guardare
cast_bar_inline.dartgoogle_cast_controller.dartcustom_cast_controller.dartCastQueueManager.kt
Fix tipico
- usare
startIndex: 0nei comandi manuali della cast bar - oppure proteggere con una funzione tipo
_safeIndexOrKeep(...)
Problema: seek sul video cambia sulla TV ma non sul telefono
Causa probabile
Il telefono usa un player locale non sincronizzato con positionNotifier / isPlayingNotifier del Cast.
Dove guardare
google_cast_controller.dartfullscreen_cast_viewer.dart
Fix tipico
- in
seekCast()aggiornare subitopositionNotifier - nel
VideoWidgetlocale ascoltarepositionNotifiereisPlayingNotifier
Problema: il volume compare ma la barra non si aggiorna
Causa probabile
Il comando volume parte, ma il notifier locale non viene riallineato con lo stato reale del device.
Dove guardare
google_cast_controller.dartcast_controls_sheet.dartfullscreen_cast_viewer.dartCastMediaClient.kt
Fix tipico
- dopo
setVolumeesetMute, chiamarerefreshVolumeStatus() - lato UI, separare
onChangedeonChangeEnddello slider
Problema: scegli Google ma sembra partire Custom
Causa probabile
Il backend attivo del controller unificato non è allineato al backend scelto nella UI.
Dove guardare
cast_icon_button.dartcast_controller.dartcustom_cast_controller.dartgoogle_cast_controller.dart
Fix tipico
- rendere l’icona Cast “connect-only”
- impostare esplicitamente il backend attivo (
_backend) nel controller unificato - far partire la queue solo dai pulsanti della cast bar
Problema: in selection mode la app bar sembra toccare anche le foto sotto
Causa probabile
La barra non sta assorbendo correttamente i tocchi nell’area header.
Dove guardare
collection_app_bar.dartaves_app_bar.dartcollection_page.dart
Fix tipico
- ripristinare il wrapper che assorbe i tap nella barra (
AInkResponse) - verificare il comportamento
pinned - verificare l’uso corretto di
appBarHeightNotifier
6. Regole pratiche di debug
Regola 1
Se il problema è “UI Flutter non aggiornata”
Guarda prima i controller Dart:
cast_controller.dartgoogle_cast_controller.dartcustom_cast_controller.dartfullscreen_cast_viewer.dart
Regola 2
Se il problema è “la TV/device fa una cosa diversa da Flutter”
Guarda:
CastMediaClient.ktCastQueueManager.kt- receiver custom JS/HTML (se custom)
Regola 3
Se il problema avviene subito dopo la connessione device
Guarda:
CastSessionHandler.ktgoogle_cast_controller.dartCastMediaClient.kt
Il sospetto classico è la distinzione:
- connessione sessione
- queue realmente caricata
Regola 4
Se il problema riguarda slideshow foto/video
Guarda prima il controller Dart, poi il native.
Ordine consigliato:
google_cast_controller.dartcustom_cast_controller.dartCastMediaClient.ktCastQueueManager.kt
Regola 5
Se il problema riguarda il Custom Receiver
Non fermarti al controller Flutter.
Devi guardare anche:
CastCustomReceiver.ktreceiver.html- eventuale JS del receiver
Perché molti bug Custom sono receiver-side, non plugin-side.
7. Differenza pratica Google vs Custom (da tenere a mente)
Google Cast standard
Più affidabile quando:
- usi queue nativa
- usi volume Cast nativo
- ti affidi a
RemoteMediaClient.Callback
Custom Receiver
Più flessibile quando:
- vuoi UI custom sul TV
- vuoi logica media personalizzata
- vuoi controllare il player HTML5 direttamente
Ma più fragile quando:
- volume/mute non sono implementati davvero
- il DOM del receiver non viene pulito bene
- i messaggi receiver/Flutter non sono perfettamente allineati
8. Checklist rapida: dove toccare per ogni categoria
Connessione device
cast_icon_button.dartFlutterCastFrameworkPlugin.ktCastDialogLauncher.ktCastSessionHandler.kt
Queue / media non partono
cast_bar_inline.dartgoogle_cast_controller.dartCastQueueManager.kt
Slideshow foto/video
google_cast_controller.dartcustom_cast_controller.dartCastMediaClient.kt
Volume Google
google_cast_controller.dartcast_controls_sheet.dartfullscreen_cast_viewer.dartCastMediaClient.kt
Volume Custom
custom_cast_controller.dartCastCustomReceiver.ktreceiver.html/ JS
Bug UI selection / app bar
collection_app_bar.dartaves_app_bar.dartcollection_page.dart
9. Conclusione pratica
Se devi pensare al plugin in modo operativo, ricordati questa formula:
Flutter decide l’UX → il plugin Android parla con Cast → il receiver riproduce davvero
Quindi ogni bug va classificato subito in una di queste tre famiglie:
A. Bug UX / Flutter
- notifier
- selection
- fullscreen viewer
- cast bar
- app bar
B. Bug plugin Android
- sessione
- queue
- callback media
- volume nativo
C. Bug receiver
- volume custom
- progress bar duplicate
- media status custom
- UI TV-side
Capire subito in quale famiglia rientra il bug fa risparmiare tantissimo tempo di debug.