Dopo aver visto i fondamenti di Chromecast, è arrivato il momento di capire come creare un'app completa per Android. In particolare, realizzeremo un lettore multimediale che permetta di visualizzare sulla TV contenuti video, in formato .mp4, caricati su un server remoto.
In pratica:
- abbiamo caricato su un server web - via FTP - tre video, denominati 01.mp4, 02.mp4 e 03.mp4. Tanto per intenderci, l'URL di ogni risorsa sarà del tipo http://www.mioserver.it/video/01.mp4. Tali indirizzi saranno utilizzati nella nostra app ma possono tornare utili anche per una semplice verifica tramite browser per verificarne la raggiungibilità;
-
nella medesima cartella del server - denominata video - collochiamo un semplice script PHP in grado di fornire l'elenco dei file presenti in essa: in situazioni reali, lo script sarebbe probabilmente sostituito con un componente lato server più robusto:
<?php $dir = "."; $res = array(); if($dh = opendir($dir)){ while(($file = readdir($dh)) != false){ if($file == "." or $file == ".." or substr($file,-3)!="mp4") continue; $res[] = $file; } } echo json_encode($res); ?>
L'output prodotto somiglierà al seguente:
["03.mp4","02.mp4","01.mp4"]
- la nostra app Android, come operazione preliminare, invocherà tramite la libreria Volley lo script PHP, e recupererà l'elenco dei nomi di file: il loro URL completo sarà ricavabile nella maniera spiegata al primo punto;
- nell'interfaccia dell'Activity verrà collocata una ListView contenente l'elenco dei file disponibili, per ognuno dei quali sarà mostrato un apposito pulsante per avviare o interrompere la riproduzione del video:
- ogni volta che ordineremo di avvieremo la lettura di un file multimediale, Chromecast si collegherà via Internet all'URL del video e lo riprodurrà sul nostro televisore. Con i pulsanti che abbiamo inserito nella ListView possiamo gestire la fruzione del contenuto ed il passaggio ad un altro video presente nella lista.
L'Activity
Nel metodo onCreate implementeremo pre lo più tre funzionalità:
- inizializzeremo il MediaRouter, che utilizzeremo per rintracciare i dispositivi Chromecast disponibili nella rete locale;
- istanzieremo una coda delle richieste di Volley;
- prepareremo la ListView ed un ArrayAdapter, seguento l'approccio standard.
public class MainActivity extends AppCompatActivity
implements GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks{
private static final String BASE_URL="http://www.mioserver.it/video/";
private static final String URL=BASE_URL+"list.php";
@Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* OMISSIS: preparazione del MediaRouter come nella lezione precedente */
mRequestQueue = Volley.newRequestQueue(this);
StringRequest request = new StringRequest(URL, listener, errorListener);
mRequestQueue.add(request);
listView = (ListView) findViewById(R.id.listview);
adapter = new ArrayAdapter<String>(this, R.layout.row_layout, R.id.filename, new ArrayList<String>());
listView.setAdapter(adapter);
}
}
La StringRequest preparata per Volley recupera i dati offerti dallo script PHP e ne fa il parsing nel Response Listener, in modo da recuperare le stringhe rappresentanti i nomi di video in formato mp4 ed inserirle direttamente nell'Adapter:
private Response.Listener<String> listener=new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response!=null && response.length()>0)
{
String[] pieces=response.replace('[',' ').replace(']',' ').trim().split(",");
for (String p: pieces)
{
adapter.add(p.replace('"',' ').trim());
}
}
}
};
Preparazione del Player
Nella lezione precedente, ci eravamo fermati al collegamento della nostra app con un dispositivio Chromecast presente nella rete LAN ed avevamo visto che tale evento viene notificato con l'invocazione del metodo onRouteSelected
dell'oggetto MediaRouterCallback
. Proprio da qui inizia la preparazione della riproduzione video:
- all'interno di
onRouteSelected
inizializzeremo un oggettoRemoteMediaPlayer
, di cui parleremo a breve, ed inizializzeremo un GoogleApiClient richiedendo supporto per le Cast API;
public void onRouteSelected(MediaRouter router, RouteInfo info) { selectedDevice = CastDevice.getFromBundle( info.getExtras() ); mediaPlayer = new RemoteMediaPlayer(); mediaPlayer.setOnStatusUpdatedListener(new RemoteMediaPlayer.OnStatusUpdatedListener() { @Override public void onStatusUpdated() { MediaStatus mediaStatus = mediaPlayer.getMediaStatus(); playing = mediaStatus.getPlayerState() == MediaStatus.PLAYER_STATE_PLAYING; } }); mediaPlayer.setOnMetadataUpdatedListener(new RemoteMediaPlayer.OnMetadataUpdatedListener() { @Override public void onMetadataUpdated() { } }); Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions .builder(selectedDevice, castListener); googleApiClient = new GoogleApiClient.Builder( MainActivity.this ) .addApi( Cast.API, apiOptionsBuilder.build() ) .addConnectionCallbacks(MainActivity.this) .addOnConnectionFailedListener( MainActivity.this ) .build(); googleApiClient.connect(); }
-
essendo la nostra Activity implementazione dell'interfaccia
GoogleApiClient.ConnectionCallbacks
, l'avvenuta connessione ai Google Play Services verrà notificata invocando il metodoonConnected
:
public void onConnected(Bundle bundle) { if(reconnecting) { reconnecting = false; reconnect(bundle); } else { try { Cast.CastApi.launchApplication(googleApiClient, CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID, false ) .setResultCallback(new ResultCallback<Cast.ApplicationConnectionResult>() { @Override public void onResult(Cast.ApplicationConnectionResult applicationConnectionResult) { Status status = applicationConnectionResult.getStatus(); if (status.isSuccess()) { started = true; reconnect(null); } } } ); } catch ( Exception e ) { } } }
dove avremo tutti gli elementi per poter lanciare un'applicazione Receiver all'interno di Chromecast: si tratta di un Default Media Receiver, il componente più basilare
Il RemoteMediaPlayer
Il RemoteMediaPlayer introdotto nel codice precedente è l'elemento centrale della riproduzione di contenuti multimediali tramite Chromecast. Al momento non ne abbiamo fatto uso, limitandoci soltanto ad istanziarlo. Si noti che nella sua configurazione hanno fatto la loro comparsa due listener:
- l'OnStatusUpdatedListener viene chiamato in causa ogni volta che interviene una modifica allo stato della riproduzione del contenuto multimediale. All'interno del suo metodo
onStatusUpdated
leggiamo un oggetto MediaStatus che contiene le informazioni sul cambiamento avvenuto e ne teniamo traccia in una variabile che ci ricorderà sempre se il contenuto è in esecuzione o meno; - l'OnMetadataUpdatedListener riferisce invece mutamenti cui è andato incontro il contenuto stesso in riproduzione ma nel nostro esempio non ne facciamo uso.
Nella prossima lezione, commenteremo i metodi necessari alla gestione dei contenuti e finalmente avremo a disposizione tutto ciò che serve a far funzionare il nostro lettore multimediale.