Android VideoView Example With Youtube Playback - Truiton
Skip to content

Android VideoView Example With Youtube Playback

Sculpture by the Sea Bondi - Best of Perth

At Truiton I was developing another app in which the requirement was to view a YouTube video inside my app. So I thought of using Android VideoView class for it. Although if we have to view local videos that are present in our device or app, still the same Android VideoView class can can be used. In this Android VideoView Example With YouTube Playback tutorial I would show how to play a streaming You Tube video in an Android device, also I would show how to place a local video.

One of the main drawbacks for using Android VideoView for streaming YouTube videos, is that it streams a very low quality video with a resolution of 176 x 144 px, in 3gp format. In my app I didn’t a needed high quality YouTube streaming hence I used Android VideoView class. But if you wish to stream high quality YouTube videos have a look on my tutorial for YouTube API in my complete series on streaming videos:

  1. Android VideoView Example With YouTube Playback
  2. Android YouTube API

Android VideoView

Lets start off with an intro of Android VideoView. In short its an Android widget which eases the process of video playback on device. It gives the user an abstraction from JNI code, i.e. the MediaPlayer-JNI class. Yes the fact is Android VideoView is just a wrapper around the MediaPlayer class of android. Now since we are using a wrapper there are some limitations regarding the types of supported file types. In android only the file types listed below can be played with Android VideoView class:

  1. H.263
    • 3GPP (.3gp)
    • MPEG-4 (.mp4)
  2. H.264 AVC
    • 3GPP (.3gp)
    • MPEG-4 (.mp4)
    • MPEG-TS (.ts, AAC audio only, not seekable, Android 3.0+)
  3. MPEG-4 SP
    • 3GPP (.3gp)
  4. VP8
    • WebM (.webm)
    • Matroska (.mkv, Android 4.0+)

Moving on lets have a look at the layout I am going to use for this Android VideoView Example With YouTube Playback :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".VideoViewActivity"
    android:background="#000000" >

    <VideoView
        android:id="@+id/videoView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

</RelativeLayout>

It is not as simple as it seems to play a YouTube video on android with VideoView as the format which YouTube uses for streaming is not supported by android directly. Therefore the workaround for this, is to use 3gpp format. YouTube doesn’t provide the URL for this format directly, therefore to get this URL we need to query the “http://gdata.youtube.com/feeds/api/videos/” URL. This URL returns a file from which we can get the URL for 3gpp format video. Now the interesting part is that there’s another limitation by YouTube’s policies that download of a video is not permitted. Hence the URL returned is of RTSP (Real Time Streaming Protocol) format. Luckily this protocol is supported by our Android VideoView class and the video is streamed instead of download. Lets have a look at the code for this process:

package com.truiton.videoview;

import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.MediaController;
import android.widget.VideoView;

public class VideoViewActivity extends Activity {
	private VideoView videoView;
	private MediaController mController;
	private Uri uriYouTube;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_video_view);
		videoView = (VideoView) findViewById(R.id.videoView1);
		mController = new MediaController(this);
		videoView.setMediaController(mController);
		videoView.requestFocus();

		/*Uri uri = Uri.parse("android.resource://" + this.getPackageName() + "/"
				+ R.raw.sample);
		videoView.setVideoURI(uri);
		videoView.start();*/

		if (savedInstanceState != null) {
			int loc = savedInstanceState.getInt("Loc");
			Log.i("Loaction: ", loc + "");
			uriYouTube = Uri.parse(savedInstanceState.getString("url"));
			videoView.setVideoURI(uriYouTube);
			videoView.seekTo(loc);
			videoView.setOnPreparedListener(new OnPreparedListener() {
				@Override
				public void onPrepared(MediaPlayer mp) {
					Log.v("onPrepared", "ok");
					mp.start();
				}
			});
		} else {
			RTSPUrlTask truitonTask = new RTSPUrlTask();
			truitonTask.execute("http://www.youtube.com/watch?v=2zNSgSzhBfM");
		}

	}

	void startPlaying(String url) {
		uriYouTube = Uri.parse(url);
		videoView.setVideoURI(uriYouTube);
		videoView.start();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putInt("Loc", videoView.getCurrentPosition());
		outState.putString("url", uriYouTube.toString());
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.video_view, menu);
		return true;
	}

	private class RTSPUrlTask extends AsyncTask<String, Void, String> {
		@Override
		protected String doInBackground(String... urls) {
			String response = getRTSPVideoUrl(urls[0]);
			return response;
		}

		@Override
		protected void onPostExecute(String result) {
			startPlaying(result);
		}

		public String getRTSPVideoUrl(String urlYoutube) {
			try {
				String gdy = "http://gdata.youtube.com/feeds/api/videos/";
				DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance()
						.newDocumentBuilder();
				String id = extractYoutubeId(urlYoutube);
				URL url = new URL(gdy + id);
				HttpURLConnection connection = (HttpURLConnection) url
						.openConnection();
				Document doc = dBuilder.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;
			}
		}

		public 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;
		}
	}

}

Here in the above code what I am trying to do is stream a YouTube video in the lowest quality with Android VideoView class. Another important thing that I am doing here is to resume video streaming from where it stopped when the screen is rotated.

In the above code the RTSP URL is parsed in a separate thread as in the new Android API, network access is not allowed on main thread, if we try to access network it would throw NetworkOnMainThreadException. This task to parse URL for Android VideoView is started from lines 62-63 by RTSPUrlTask which is a AsyncTask.

Now the tricky part accomplished here, is to resume the video playback in Android VideoView from where it stopped after the screen is rotated. To resume video playback in Android VideoView from where it stopped I am using Android’s callback method onSaveInstanceState. In this method I am storing a two parameters first the current location of video playback and the second video URL. Now if you have a close look at the class above, in lines 48 – 64 I am checking whether a savedInstanceState exists or not. If it exists its obvious that in current scenario screen is rotated. Hence the YouTube playback in Android VideoView starts from the location stored in savedInstanceState.

Can’t play this video

As of now if you run this code you would probably get this error. According to me this Can’t play this video notification comes in two cases :

  1. Unsupported file format
  2. Due to missing internet access permissions

In this Android VideoView tutorial I am showing how to stream a YouTube video live from internet, hence it is required to add the following permissions in the app’s manifest to make the above notification go away:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

After adding the permissions if you run the Android VideoView Example, output would be something like:

Android VideoView

Now since Android VideoView is a widget used to play videos, it can also be used to play videos that are stored locally on the device. To play a video that is locally available on device is comparatively simpler. In the above VideoViewActivity class have a look at the commented out lines 43 – 46 :

Uri uri = Uri.parse("android.resource://" + this.getPackageName() + "/"
				+ R.raw.sample);
		videoView.setVideoURI(uri);
		videoView.start();

Just add a video in res/raw folder of your project, un-comment these lines and give its reference in the above setVideoURI method and your task would be accomplished. Also comment out the lines 48-64, so that YouTube code is not compiled. Although Android VideoView cannot be used to play videos in assets folder, if you wish to do that you can use the Android MediaPlayer class. With this I would conclude Android VideoView Example With Youtube Playback tutorial, if you liked this tutorial please share it with your friends on Google+ and Facebook.

7 thoughts on “Android VideoView Example With Youtube Playback”

  1. What happens with memory performance? in case of a youtube video or a local video , if you want to play lets say 10 videos?

  2. hai mohit gupt: i want to run the live tv channel from yotube using corresponding url…as u said above and also i added the youtube api demo (sdk)from https://www.youtube.com/yt/dev/ i did perfectly…but i cannot get the solution!! can u help me out..!! and can anyone send the programming code for playing the live tv channel from youtube..!! i have been working 15 days !! i strucked here!!!

    sorry for my poor english and thanks in advance!!

  3. Still got”Can’t play this video”after I set the permission.

    Got something:

    E/ViewRootImpl﹕ sendUserActionEvent() mView == null
    E/MediaPlayer﹕ error (1, -2147483648)
    E/MediaPlayer﹕ Error (1,-2147483648)

    What could be wrong? Or Youtube doesn’t allow us to do so now? Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *