我不知道该怎么做。请建议如何分批下载大型视频文件并逐个播放所有部分。
实际上我必须在Android VideoView
中传输FTP大文件。我搜索了很多,发现android不支持FTP流媒体。
所以,我尝试将文件分多个部分下载并逐个播放。但问题是只有文件的第一部分播放,有些则不播放。请建议。
部分下载文件的代码。
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);
}
}
当下载文件时,我尝试更新列表,以便在下载至少1个文件时播放视频。 listFiles包含所有已下载文件的列表。
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();
}
}
});
我不知道为什么文件1之后的下载文件无法播放。它们即使在PC中也不会播放。我不知道我做错了什么。
答案 0 :(得分:2)
您可以创建用于流式传输视频的本地服务器(ServerSocket
)。
创建后台线程,您可以直接使用FTP获取流并将相同的日期写入本地服务器的输出流。当您完成一个文件的下载后,您可以打开第二个文件,但仍然使用本地服务器的相同输出流。
在VideoView
中,您将打开127.0.0.1:PORT
,其中包含您将为本地服务器打开的端口。我建议使用IP而不是localhost
,因为在过去我遇到了一些设备无法识别域localhost
的问题。凭借IP,我从未遇到任何问题。
请注意,在本地服务器中,您需要在数据之前发送HTTP标头。
答案 1 :(得分:1)
以这种方式解码文件不会播放所有文件。因为它们只是二进制文件而您正在尝试更改它们的扩展名。 android中没有办法以这种方式解码文件。但是有许多库可用于将文件解码为部分,然后分别播放每个部分。其中一个库是ffmpeg。
答案 2 :(得分:0)
如果将View文件拆分为多个部分,则只有第一部分包含格式规范。这就是你第一部分上场的原因。所有其他部分都只是二进制文件。
下载完所有部件后,必须按相同的顺序合并它们。
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");
}
}
答案 3 :(得分:0)
您可以创建ContentProvider并使用其Uri初始化VideoView,而不是构建本地服务器。通常我们使用ContentProvider将一些数据传递给具有SQL访问权限的其他应用程序,但这里它将是一个提供二进制数据的应用程序内提供程序。
Here is a tutorial,展示了如何使用ContentProvider处理二进制数据。
答案 4 :(得分:-1)