How to stream and download a video using VideoView in Android

Hi there,

It’s been a while I haven’t written anything here, well was busy with my new company and consulting others!

A customer of mine wants to download and play video simultaneously at first I was confidence that  requirement is easy! But it was only a dream because android’s SDK support no such functionality for whatever reason.

But hopefully VideoView supports http streaming and it leads me to implement a HTTP internal server as a fake http streaming server and ask VideoView to get data from it!

it sound quite easy but there are loads of things that you need to take care.

1-creating a HTTP server, thanks Lord there is one for free NanoHTTPD

2-read data in chunks and send it back to VideoView

3-respond to VideoView so it could request for other chunks.

for this part you have to check if VideoView is sending request with “Range” header if not it means it is the first time so you have to response with “Content-Range: bytes 0-YOUR_CHUNK” also you have to send the “Content-Length : full length of file” so that VideoView could request back for other chunks and at the end don’t forget to send your response with “206” not with “200”.

“HTTP 206” means partial data!

4-your video files must be encoded correctly otherwise it doesn’t work at all, you can read full article here or just simply download ffmpeg and encode your video with that!

the rest is code : I just copied the useful part here, you can find the full solution in my github

 

    public class VideoStreamServer extends NanoHTTPD
    {
 
        public VideoStreamServer(int port) {
            super(port);
        }
 
        @Override
        public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files) {
 
            //range=bytes=619814-
            long range;
 
            if (headers.containsKey("range"))
            {
                String contentRange = headers.get("range");
                range = Integer.parseInt(contentRange.substring(contentRange.indexOf("=") + 1, contentRange.indexOf("-")));
            }
            else
                range = 0;
 
            byte[] buffer;
            int constantLength = 256000;
            long bufLength=0;
            boolean isLastPart=false;
            try {
 
                RandomAccessFile ff =new RandomAccessFile(new File("/mnt/sdcard","1.mp4"),"rw" );
                long remainingChunk = ff.length() - range; //remaining
                if (remainingChunk < constantLength){
                    bufLength= remainingChunk; //means last part
                    isLastPart = true;
                }
 
                else
                    bufLength = constantLength;
                if (range !=0)
                    ff.seek(range);
                buffer= new byte[(int)bufLength];
 
                ff.read(buffer);
 
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                buffer = new byte[0];
            } catch (IOException e) {
                e.printStackTrace();
                buffer = new byte[0];
            }
            Response response;
 
                response = new Response(Response.Status.PARTIAL_CONTENT,"video/mp4",new ByteArrayInputStream(buffer));
 
            response.addHeader("Content-Length","891064");
            response.addHeader("Content-Range",String.format("bytes %s-%s/%s", range,(range+bufLength),"891064"));
            Log.e("SERVER","Inside server sent " + String.format("bytes %s-%s/%s", range,(range+bufLength),"891064"));
            return response;
 
        }
    }

Android AsyncTask and How To Make It Less Painful

If you are an android developer you probably know for doing tasks that take too much time from processor or tasks that keep the user waiting for couple of seconds if you run such task on current thread, android will  freeze the UI therefore you have to develop your application in multi-threading fashion and one of the solutions for making the app multi-threaded is by using AsyncTask abstract class.

Let us check the way of using AsyncTask in a very simplistic example :

(Assume you want to get a page from a url) :

 private class DownloadFilesTask extends AsyncTask {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }
 
     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }
 
     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

For executing AsyncTask:

new DownloadFilesTask().execute(url1, url2, url3);

Reference : http://developer.android.com/reference/android/os/AsyncTask.html

But what if you want to use AsyncTask in several different places?
Suppose you want to do several different tasks (e.g. counting a long list or process a text, etc…) If you want to implement AsyncTask everywhere you will end up with a stack of codes which are literally doing the same thing but with very minor changes.

So I thought how can I make it less painful?
I started to write one generic class for AsyncTsak to make it generic and I ended up with something as  following :

But its not the whole story for using this generic class I invent a technique (not quite sure if I can call it “design pattern”) to make it easier to use you need to create following interface as well:

Then inside your actual class you need to implement the ITask and then initialize  the overridden  methods then at the end instantiate the ParrelelTask class to run the actual AsyncTask class behind the scene.

here you can download the sample code to see it in action.

Conclusion

By the help of this technique I manage to reduce lines of codes from several classes inside my real application but yet this technique is not efficient and I think it still can be polished to become less confusing, and remember AsyncTask is not very efficient  in terms of doing several tasks at the same time. The whole idea of AsyncTask is keeping away the UI from freezing for having an actual muti-thread application you need to use JAVA threading APIs.

At the end let me know if you have better way of designing a technique or pattern for calling AsyncTask.