Android VideoView e le Youtube Api

di  Antonio Coschignano, lunedě 10 gennaio 2011

In questo articolo esaminiamo una caratteristica interessante dell'ambiente Android cioè la possibilità di poter integrare all'interno delle nostre applicazioni la riproduzione dei video. Questo ci viene consentito dal componente VideoView che è un vero e proprio controllo grafico che può essere integrato all'interno di un layout insieme a tutti gli altri componenti definiti nella piattaforma. E' sicuramente un componente che va utilizzato con cautela poichè richiede molte risorse ma allo stesso tempo è molto semplice da implementare.

Implementare la VideoView

La classe VideoView ci consente la riproduzione audio/video del tipo 3gp/mp4, per maggiori dettagli consultate questa tabella Media Formats (contiene le specifiche degli stream in questione). Essendo una sottoclasse di View ne eredita tutte le caratteristiche, quali anche la possibilità di impostare le dimensioni che vogliamo. Come per tutti le altre View ci sono due modi per ottenere un'istanza di questo oggetto. Attraverso la dichiarazione XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
...
<VideoView
	android:id="@+id/VideoViewDemo"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content">
</VideoView>
...
</LinearLayout>

...

public class ActivityVideoViewDemo extends Activity {

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.setContentView(R.layout.main);
    VideoView videoView = (VideoView) findViewById(R.id.VideoViewDemo);
    ...
  }
  ...
}
Oppure direttamente da codice:
public class ActivityVideoViewDemo extends Activity {

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.setContentView(R.layout.main);
    VideoView videoView = VideoView(this);
    ...
  }
  ...
}
Una volta ottenuta l'istanza bisogna specificare il percorso del video da riprodurre utilizzando i seguenti metodi a secondo della locazione del video:
  • tramite il metodo setVideoPath(String percorso): questo per riprodurre il video che risiede sul dispositivo. Ad esempio:
    VideoView videoView ....
    videoView.setVideoPath("/data/data/package-xxx/files/video,mp4");
    
  • tramite setVideoURI(Uri uri): se il video risiede su un server web. Il percorso del video in questo caso va specificato sottoforma di oggetto android.net.Uri che possiamo ottenere tramite il metodo statico Uri.parse(). Esempio:
    VideoView videoView ....
    Uri uri = Uri.parse("http://www.example.com/miovideo.mp4");
    videoView.setVideoURI(uri);
    
Per avviare la riproduzione del video, invochiamo il metodo start():
videoView.start();

MediaController

Il metodo start() avvia la riproduzione del video senza però che l'utente abbia nessun controllo su di esso. Per ottenere anche un controllo sulla riproduzione del video (stop, pause etc..) bisogna aggiungere il MediaController che aggiunge alla VideoView i classici controlli per la gestione dei media:

import android.widget.MediaController;
...
MediaController controller = new MediaController(MyActivity.this);
videoView.setMediaController(controller)
Cosi facendo abbiamo aggiunto in maniera rapida i controlli che vengono visualizzati non appena tocchiamo l'area dello schermo dove viene visualizzato il video.

Listeners

Per avere invece un controllo sul flusso della riproduzione direttamente dal codice, cioè implementare delle azioni quando ad esempio il video inizia oppure finisce possiamo utilizzare rispettivamente le interfacce OnPreparedListener e OnCompletionListener:

import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
....
class VideoStarted implements OnPreparedListener {
  	@Override
	public void onPrepared(MediaPlayer mp) {
	  ...
	}
}
....
class VideoPlayComplete implements OnCompletionListener {
  @Override
  public void onCompletion(MediaPlayer mp) {
  	...
  }
}
...
VideoView videoView = ...
....
videoView.setOnPreparedListener(new VideoStarted());
videoView.setOnCompletionListener(new VideoPlayComplete());
L' oggetto MediaPlayer è una particolare componente che viene implementato per controllare il flusso della riproduzione audio/video. Infatti viene passata come argomento ai metodi delle interfaccie e quindi possiamo compiere delle azioni sulla riproduzione: pause(), reset(); oppure ottenere delle informazioni come: getCurrentPosition(), getDuration() etc..

VideoView e i video Youtube

Riprodurre i video Youtube all'interno di una VideoView non è un 'operazione immediata, ma bisogna eseguire prima alcune operazioni. I classici video Youtube non sono in formato 3gp quindi se utilizziamo direttamemnte l'url del video all'interno della VideoView non otterremo nessuna riproduzione. Per fortuna alla maggior parte di questi video è associato anche il formato 3gp per la riproduzione sui dispositivi mobili. Quindi il problema adesso è riuscire ad ottenere l'url per il video in questo formato. Esistono le Youtube API che ci consentono - attraverso richieste http - di reperire ulteriori informazioni che riguardano un generico video. Ad esempio possiamo ottenere i commenti, l'autore, il titolo etc.. in formato XML. Quindi dove è presente, anche la risorsa RTSP (Real Time Straming Protocolo) del video in formato 3gp. Ad esempio se abbiamo una url Yotube del tipo:

http://www.youtube.com/watch?v=hPUGNCIozp0
Quello che vedete in grassetto rappresenta l'id del video. Tramite l'id bisogna effettuare una chiamata alle API accodando l'id all'indirizzo :
http://gdata.youtube.com/feeds/api/videos/
Ci viene restituita un documento XML con tutte le informazioni del video, tra cui anche l'indirizzo della risorsa 3gp:
rtsp://v2.cache2.c.youtube.com/xxxxxxxxxxxxxxxxxxxxxxxxxxxw=/0/0/0/video.3gp
Ma senza scendere nei dettagli ho preparato un metodo che dato una generica URL di Youtube ne estrae (se č presente) il percorso 3gp da riprodurre nella VideoView utilizzando le Youtube API:
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;


import javax.xml.parsers.*;
import org.w3c.dom.*;

....

public static String getUrlVideoRTSP(String urlYoutube) {
  try {
    String gdy = "http://gdata.youtube.com/feeds/api/videos/";
    DocumentBuilder documentBuilder = DocumentBuilderFactory
      .newInstance().newDocumentBuilder();
    String id = extractYoutubeId(urlYoutube);
    URL url = new URL(gdy+id);
    HttpURLConnection connection = (HttpURLConnection) url
      .openConnection();
    Document doc = documentBuilder.parse(connection.getInputStream());
    Element el = doc.getDocumentElement();
    NodeList list = el.getElementsByTagName("media:content");
    String cursor = urlYoutube;
    for (int i = 0; i < list.getLength(); i++) {
      Node node = list.item(i);
      if (node != null) {
        NamedNodeMap nodeMap = node.getAttributes();
        HashMap<String, String> maps = new HashMap<String, String>();
        for (int j = 0; j < nodeMap.getLength(); j++) {
          Attr att = (Attr) nodeMap.item(j);
          maps.put(att.getName(), att.getValue());
        }
        if (maps.containsKey("yt:format")) {
          String f = maps.get("yt:format");
          if (maps.containsKey("url"))
            cursor = maps.get("url");
          if (f.equals("1"))
            return cursor;
        }
      }
    }
    return cursor;
  } catch (Exception ex) {
    return urlYoutube;
  }

  protected static String extractYoutubeId(String url) throws MalformedURLException {
    String query = new URL(url).getQuery();
    String[] param = query.split("&");
    String id = null;
    for (String row : param) {
      String[] param1 = row.split("=");
      if (param1[0].equals("v")) {
        id = param1[1];
      }
    }
    return id;
  }
}
Questo metodo in poche parole implementa un parser XML che estrae il media content rtsp in base alla chiamata API che abbiamo effettuato. Quindi una volta ottenuto la risorsa 3gp/mp4 basta impostarla nel componente. Esempio:
VideoView videoView = ...
String urlYoutube = "http://www.youtube.com/watch?v=hPUGNCIozp0";
String urlRtsp = getUrlVideoRTSP(urlYoutube);//Il metodo che abbiamo visto
videoView.setVideoURI(Uri.parse(urlRtsp));
MediaController controller = new MediaController(MyActivity.this);
videoView.setMediaController(controller);
videoView.start();

Esempio VideoView (Applicazione completa)

Per concludere vi lascio con l'esempio di un'applicazione completa che riproduce i video youtube all'interno di una VideoView. Il layout è composto da una EditText per inserire la url Youtube, un Button per avviare la riproduzione e la VideoView. L'applicazione implementa gli argomenti che abbiamo visto in quest'articolo compreso l'utilizzo dei listeners. Ecco gli screenshot dell'applicazione:

Esempio di VideoViewDemo Applicazione Android Youtube

Scarica il progetto VideoViewDemo Android Eclipse in formato zip

Altri link che potrebbero interessarti
  • » Struttura di un'applicazione Android
  • » Screenshot su un dispositivo Android
  • » Pubblicare applicazioni nell'Android Market
  • » Integrare Google Analytics nelle applicazioni Android
  • » Integrare AdMob nelle applicazioni Android
  • » Guida all'installazione dell'Android SDK
  • » Guida agli Adapter e le ListView in Android
  • » Gestire Thread e GUI nelle applicazioni Android
  • » Applicazioni Android ed il supporto multilingue
  • » Android Linkify e i collegamenti testuali
  • » Android HTML TextView
  • » Android e tecniche multithreading
  • » Android e la gestione dei sensori
  • » Android e l'interfaccia Parcelable