0

I don't know how to do. Please suggest how to download a large video file in parts and play all parts one by one. Actually I have to stream FTP large file in Android VideoView. I have searched a lot and found that android do not support FTP streaming.

So, I tried to download the file in multiple parts and play them one by one. But the problem is that only first part of file plays, others don't. Please suggest.

Code to download file in parts.

URL url = new URL(fileUrl);
URLConnection ucon = url.openConnection();
InputStream is = ucon.getInputStream();
BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5);
FileOutputStream outStream = new FileOutputStream(fileName);
byte[] buff = new byte[5 * 1024];
int len;

int maxLenth = 10000;      //Some random value
int counter = 0;

//Read bytes (and store them) until there is nothing more to read(-1)
 while ((len = inStream.read(buff)) != -1) {
      outStream.write(buff, 0, len);
      counter ++;
      Log.d(TAG, "Counter: " + counter);

      if(counter == maxLenth) {
          counter = 0;
          outStream.flush();
          outStream.close();

          fileName = new File(directory.getAbsolutePath() + "/"
                        + context.getResources().getString(R.string.app_name) + "_"
                        + System.currentTimeMillis() + "." + format);
          fileName.createNewFile();
          outStream = new FileOutputStream(fileName);
      }
  }

And when the files are downloaded, I tried to update the list to play videos when at least 1 file is downloaded. listFiles contains list of all the dowloaded files.

    Uri uri = Uri.parse(listFiles.get(0));
    videoView.setVideoURI(uri);
    videoView.start();

    videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            counter ++;
            if(counter < listFiles.size()) {
                Uri uri = Uri.parse(listFiles.get(counter));
                videoView.setVideoURI(uri);
                videoView.start();
            }
        }
    });

I don't know why the downloaded files after file 1 don't play. They don't play even in the PC. I don't know what wrong am I doing.

Rakesh Yadav
  • 1,966
  • 2
  • 21
  • 35

5 Answers5

2

You can create local server (ServerSocket) for streaming a video.

Create background thread and you can directly use FTP to get the stream and write same date to the output stream of local server. When you will finish download of one file, you can open second file, but still use same output stream of the local server.

In the VideoView you will open 127.0.0.1:PORT with the port that you will open for local server. I recommend using IP instead of localhost, because in the past I encountered issues that some devices didn't recognized domain localhost. With IP I never had any issue.

Please note, that in your local server you will need to send HTTP header before the data.

https://stackoverflow.com/a/34679964/5464100

Milos Fec
  • 828
  • 6
  • 11
  • Thanks for your suggestion, but do you know that Android doesn't provide FTP streaming of videos. – Rakesh Yadav Nov 11 '17 at 16:01
  • This is OK here, because the fake server uses HTTP to stream the combined video to the VideoView. FTP is used to download the pieces as you tried before. – Alex Cohn Nov 12 '17 at 21:09
2

Decoding file this way will not play all the files. Because they are just binary files and you are trying to change the extensions of them. There is no way in android to decode files this way. But there are many libraries which you can use to decode the file into parts and then play each part separately. One of the library is ffmpeg.

0

If you split a View file into parts, only the first part will contain the format specifications. This is the reason only your first part is getting played. All the other parts are just binary files.

After you have downloaded all the Parts, you have to merge them in the same sequence.

private void mergeAfterDownload()
{
    Log.i(LOG_TAG, "Merging now");

    try {
        File destinationFile = new File("Path to the Merged File");
        if (destinationFile.exists()) destinationFile.delete();

        // Create the parent folder(s) if necessary
        destinationFile.getParentFile().mkdirs();
        // Create the file
        destinationFile.createNewFile();

        FileOutputStream destinationOutStream = new FileOutputStream(destinationFile);

        // Enumerate through all the Parts and Append them to the destinationFile
        for (File file : listFiles) {
            // Read the Part
            InputStream inStream = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(inStream);

            // Append the Part to the destinationFile
            byte[] buffer = new byte[1024];
            int read;
            while ((read = bis.read(buffer)) != -1) {
                destinationOutStream.write(buffer, 0, read);
            }

            bis.close();
            inStream.close();

            //Delete the Slice
            file.delete();
        }

        destinationOutStream.close();

        Log.i(LOG_TAG, "File Merge Complete");
    }
    catch (Exception e) {

        e.printStackTrace();
        Log.e(LOG_TAG, "Failed to merge file");
    }
}
anemo
  • 1,327
  • 1
  • 14
  • 28
  • 1
    This means that you cannot start playback before all 5KB parts are downloaded. – Alex Cohn Nov 12 '17 at 20:46
  • This means I won't be able to stream until all the parts are downloaded. So this doesn't meet the requirements. – Rakesh Yadav Nov 13 '17 at 10:22
  • @RakeshYadav, your code is not performing streaming.and your question does not ask a solution for streaming either.In your question, you are specifically asking a solution for playing your files after downloading, and my answer provides a working solution for the same. – anemo Nov 13 '17 at 11:11
  • just bringing the question title to your notice "Java Android download video in parts and Play combined" – anemo Nov 13 '17 at 11:14
0

Instead of building a local server, you can create a ContentProvider and use its Uri to initialize the VideoView. Usually we use ContentProvider to pass some data to other apps with kind of SQL access, but here it will be an intra-app provider which delivers binary data.

Here is a tutorial that shows how to handle binary data with ContentProvider.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
-1

I tried a lot of things and none of them worked. Android APIs currently doesn't support this feature. So I have to rely on native code to decode the video and then encode.

To do that I will have to learn few things before such as JNI and NDK. Then I will have to apply native code. I have heard of a good library that supports these features ffmpeg which provides many features. But currently I am engaged in another project so I could not try that library and all these things.

Rakesh Yadav
  • 1,966
  • 2
  • 21
  • 35
  • I am sorry to disappoint you, but neither JNI nor ffmpeg will help you to achieve your goal better than the [solution](https://stackoverflow.com/a/47226781/192373) proposed by Mills. – Alex Cohn Nov 13 '17 at 20:06
  • Both the problem is that I can't use server otherwise I would have used http without any problem. – Rakesh Yadav Dec 09 '17 at 17:20