aves_mio100/ARCHITETTURA_PLUGIN_google_cast_pratica.md
2026-07-06 14:52:45 +02:00

15 KiB
Raw Permalink Blame History

Plugin plugins/google_cast Guida pratica / Debug operativo

Questa guida è la versione pratica del documento di architettura del plugin google_cast.

Lobiettivo è 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
  • onCastReady genera 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 sullicona 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.custom direttamente

👉 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 lindice 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:

  • CastContext
  • Activity
  • 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:

  • onSessionStarted
  • onSessionResumed
  • onSessionEnded
  • onCastReady
  • onCastStopped

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:

  • licona 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:

  • onQueueIndexChanged non arriva più a Flutter
  • onVideoFinished non arriva
  • Invalid 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 lavvio 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

  • showCastDialog
  • startCustomReceiver

Queue / navigazione

  • loadQueue
  • next
  • prev

Media

  • play
  • pause
  • seekTo
  • getMediaStatus

Volume

  • getVolume
  • setVolume
  • setMute

Stop

  • stopCast

4. Mappa degli eventi di ritorno

Google Cast standard → Flutter

  • onCastReady
  • onCastStopped
  • onQueueIndexChanged
  • onVideoFinished
  • onCastError

Custom Receiver → Flutter

Di solito via messaggi custom, per esempio:

  • CAST_READY
  • CAST_STOPPED
  • MEDIA_STATUS
  • VOLUME_STATUS

5. Troubleshooting rapido

Problema: seleziono il device e subito compaiono

  • Invalid Request
  • MediaQueue error 2001
  • IDLE_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.dart
  • CastMediaClient.kt

Fix tipico

  • non avviare startMediaPolling() dentro onCastReady
  • 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.dart
  • CastMediaClient.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.dart
  • custom_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.dart
  • custom_cast_controller.dart
  • cast_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.dart
  • google_cast_controller.dart
  • custom_cast_controller.dart
  • CastQueueManager.kt

Fix tipico

  • usare startIndex: 0 nei 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.dart
  • fullscreen_cast_viewer.dart

Fix tipico

  • in seekCast() aggiornare subito positionNotifier
  • nel VideoWidget locale ascoltare positionNotifier e isPlayingNotifier

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.dart
  • cast_controls_sheet.dart
  • fullscreen_cast_viewer.dart
  • CastMediaClient.kt

Fix tipico

  • dopo setVolume e setMute, chiamare refreshVolumeStatus()
  • lato UI, separare onChanged e onChangeEnd dello 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.dart
  • cast_controller.dart
  • custom_cast_controller.dart
  • google_cast_controller.dart

Fix tipico

  • rendere licona 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 nellarea header.

Dove guardare

  • collection_app_bar.dart
  • aves_app_bar.dart
  • collection_page.dart

Fix tipico

  • ripristinare il wrapper che assorbe i tap nella barra (AInkResponse)
  • verificare il comportamento pinned
  • verificare luso corretto di appBarHeightNotifier

6. Regole pratiche di debug

Regola 1

Se il problema è “UI Flutter non aggiornata”

Guarda prima i controller Dart:

  • cast_controller.dart
  • google_cast_controller.dart
  • custom_cast_controller.dart
  • fullscreen_cast_viewer.dart

Regola 2

Se il problema è “la TV/device fa una cosa diversa da Flutter”

Guarda:

  • CastMediaClient.kt
  • CastQueueManager.kt
  • receiver custom JS/HTML (se custom)

Regola 3

Se il problema avviene subito dopo la connessione device

Guarda:

  • CastSessionHandler.kt
  • google_cast_controller.dart
  • CastMediaClient.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:

  1. google_cast_controller.dart
  2. custom_cast_controller.dart
  3. CastMediaClient.kt
  4. CastQueueManager.kt

Regola 5

Se il problema riguarda il Custom Receiver

Non fermarti al controller Flutter.

Devi guardare anche:

  • CastCustomReceiver.kt
  • receiver.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.dart
  • FlutterCastFrameworkPlugin.kt
  • CastDialogLauncher.kt
  • CastSessionHandler.kt

Queue / media non partono

  • cast_bar_inline.dart
  • google_cast_controller.dart
  • CastQueueManager.kt

Slideshow foto/video

  • google_cast_controller.dart
  • custom_cast_controller.dart
  • CastMediaClient.kt

Volume Google

  • google_cast_controller.dart
  • cast_controls_sheet.dart
  • fullscreen_cast_viewer.dart
  • CastMediaClient.kt

Volume Custom

  • custom_cast_controller.dart
  • CastCustomReceiver.kt
  • receiver.html / JS

Bug UI selection / app bar

  • collection_app_bar.dart
  • aves_app_bar.dart
  • collection_page.dart

9. Conclusione pratica

Se devi pensare al plugin in modo operativo, ricordati questa formula:

Flutter decide lUX → 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.