Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Download video along with playing

Tags:

android

I want to implement online video playing functionality along with downloading it. I mean same download stream should be used to download and play so that video can be saved for offline use and prevent two times data cost for playing and downloading separately.

So far i have implemented video downloading with asyncTask and play it on OnPostExecute. Following is the code:

public class MainActivity extends AppCompatActivity {


private Button btnPlay;
private MediaPlayer player;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    outFilePath = getExternalFilesDir("/") + "/video.mp4";
    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

    prepareVideoView();

}

private VideoView videoView;
String videoPath = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_5mb.mp4";
String outFilePath = "";//

private void prepareVideoView() {
    MediaController mediaController = new MediaController(this);
    videoView = (VideoView) findViewById(R.id.videoView);
    mediaController.setAnchorView(videoView);
    videoView.setMediaController(mediaController);
    btnPlay = (Button) findViewById(R.id.btnPlayVideo);
    btnPlay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new VideoDownloader().execute(videoPath);
        }
    });

    videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            player = mp;

            player.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
                @Override
                public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                    Log.w("download","size changed");
                }
            });
        }
    });
}
File outFile;
class VideoDownloader extends AsyncTask<String, Integer, Void> {

    @Override
    protected Void doInBackground(String... params) {


        outFile = new File(outFilePath);
        FileOutputStream out = null;
        BufferedInputStream input = null;
        try {
            out = new FileOutputStream(outFile,true);

            try {
                URL url = new URL(videoPath);

                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.connect();
                if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                    throw new RuntimeException("response is not http_ok");
                }
                int fileLength = connection.getContentLength();

                input = new BufferedInputStream(connection.getInputStream());
                byte data[] = new byte[2048];
                long readBytes = 0;
                int len;
                boolean flag = true;
                int readb = 0;
                while ((len = input.read(data)) != -1) {
                    out.write(data,0,len);
                    readBytes += len;
   // Following commented code is to play video along with downloading but not working.
/*                      readb += len;
                    if(readb > 1000000)
                    {
                        out.flush();
                        playVideo();
                        readb = 0;
                    }
*/
                    Log.w("download",(readBytes/1024)+"kb of "+(fileLength/1024)+"kb");
                }



            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (out != null)
                    out.flush();
                    out.close();
                if(input != null)
                    input.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        Log.w("download", "Done");
       playVideo();

    }
}

private void playVideo() {

    videoView.setVideoPath(outFile.getAbsolutePath());
    videoView.start();
}
}

Above code is working properly to download and then play. There is some line of code in comment in DoInBackground that I tried to achieve my goal but it says "cant play video". Anyone knows about solution? please help me.

like image 749
chandil03 Avatar asked Dec 19 '15 13:12

chandil03


People also ask

How do I download and embed a video?

You can right-click the video directly while playing the video, and then select “Save video as” to download embedded flash video to your local hard drive. Or sometimes, you can see a download option near the full-screen button on the lower right side of the video to download embedded video directly. Simple, right?


2 Answers

You can create local proxy that will save the stream.

Create two background threads: download thread and streaming thread.

In the streaming thread create ServerSocket and stream data that are just being downloaded.

In the VideoView open the localhost url of your ServerSocket.

You will need to handle buffering, synchronizing threads etc.

like image 183
Milos Fec Avatar answered Oct 23 '22 15:10

Milos Fec


With the help of Milos Fec's answer i solved this issue. I had to create two thread one for downloading and another for streaming that downloaded content over a socketServer while taking care of synchronisation of data downloaded and data being played.

I have put the whole code as a library on github check here

EDIT: This lib does not work with all the types of videos where video servers imposes restrictions over downloading by breaking video into chunks and so on....

I have tested it with mp4 only. This lib requires a public link.

I worked on this on the early days of my Android development to just learn syncing between local server and remote server. There are a lot of room for improvements in this lib and I am not doing any because there are other options that fulfill the same requirement and I don't get enough time from my other stuff also.

like image 41
chandil03 Avatar answered Oct 23 '22 17:10

chandil03