title: How to stream and download a media from local storage using Android's VideoView?
body: <p>I have to stream and download video files from a server and show it in VideoView, well thanks to google, VV doesn't support my requirement naturally so this is what I have done:</p>
  
  <p>1-create a HTTP proxy using NanoHTTPD and start downloading a file from server</p>
  
  <p>2-start VideoView and set uri to my HTTP proxy</p>
  
  <p>3-inside server() in my proxy I started to response to VideoView same as a real server with appropriate response headers ( I mean content-length/content-range with 206 response)</p>
  
  <p>but the problem starts when VideoView, it reads like 300kb of video file properly and after that it requests from 619kb or something. I don't have any clue why would VV wants to hop from 300,000bytes and suddenly jump to 619,000bytes , and after 10 attempts it will respond me with ERROR -1004 inside c++ code of VideoView which I couldn't find any clue what is that.</p>
  
  <p>following is my complete solution.
  any help is appreciated as I became clueless about VideoView and it's bizarre behavior!!!</p>
  
  <p>Note  : I have fixed the size of file deliberately, nothing wrong with it.</p>
  
  <pre><code>package com.example.videoBuffer2;
  
  import android.app.Activity;
  import android.net.Uri;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.View;
  import android.widget.Button;
  import android.widget.MediaController;
  import android.widget.VideoView;
  
  import java.io.*;
  import java.util.Map;
  
  public class MyActivity extends Activity {
      /**
       * Called when the activity is first created.
       */
      Button btn;
      VideoView videoView;
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
          btn = (Button) findViewById(R.id.button);
          videoView = (VideoView) findViewById(R.id.videoView);
          MediaController mediaController = new
                  MediaController(this);
          videoView.setMediaController(mediaController);
          final VideoStreamServer server = new VideoStreamServer(9090);
  
          btn.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  try {
                      server.start();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
                  videoView.setVideoURI(Uri.parse("http://127.0.0.1:9090/1.mp4"));
                  videoView.requestFocus();
  
                  videoView.start();
              }
          });
      }
  
  
      public class VideoStreamServer extends NanoHTTPD
      {
  
          public VideoStreamServer(int port) {
              super(port);
          }
  
          @Override
          public Response serve(String uri, Method method, Map&lt;String, String&gt; headers, Map&lt;String, String&gt; parms, Map&lt;String, String&gt; 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 &lt; 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;
  //            if (isLastPart)
  //                response = new Response(Response.Status.OK,"video/mp4",new ByteArrayInputStream(buffer));
  //            else
                  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;
  
          }
      }
  }
  </code></pre>