我正在将 MP4 文件从 Web 应用程序下载到移动设备上的文件中。由于文件往往很大,我想在获得一些数据后立即开始播放,而不是等到整个文件下载完毕,所以我想出了以下方案:
- 将前 1 MB 的数据下载到我的 SD 卡上的文件中。
- 启动视频播放器。
- 以 1 MB 块下载剩余数据,将新数据附加到原始文件中。
更准确地说,代码执行以下操作:
创建一个名为 out 的 FileOutputstream 写入“/storage/sdcard/tmpAttachment” 从服务器获取最多 1 MB 并将其写入 /storage/sdcard/tmpAttachment 启动视频播放器并让它从 /storage/ 的开头开始播放sdcard/tmpAttachment while (更多数据) 获取下一个 1 MB 块并写入 endwhile
实际代码如下:
File file = new File(Environment.getExternalStorageDirectory() + "/tmpAttachment");
if (file.exists() && !file.delete()) { //Delete the old file if it exists
postRes = mContext.getString(R.string.message_view_dynamic_content_delete_error);
mHandler.post(mUpdateResults);
return;
}
FileOutputStream out = new FileOutputStream(file);
reply = Utility.doFetchSegment(mAccount, mMessage.getFrom()[0].getAddress() + Utility.BLANK + contentPointers[i] + Utility.BLANK + "0", "https://" + contentServerName + ":" + contentServerPort, mAccount.getEmail(), contentServerPassword, true, out, null);
if (reply[0].equals("13")) {
Uri attachmentUri = Uri.fromFile(file);
attachmentViewIntent = new Intent(mContext, ECSVideoViewer.class);
try {
ECSVideoViewer.actionECSVideoViewer(mContext, attachmentUri);
} catch (Exception e) {
postRes = mContext.getString(R.string.message_view_dynamic_content_fetch_error) + e;
mHandler.post(mUpdateResults);
e.printStackTrace();
}
while (!fPtr.equals(contentLen)) {
reply = Utility.doFetchSegment(mAccount, mMessage.getFrom()[0].getAddress() + Utility.BLANK + contentPointers[i] + Utility.BLANK + fPtr, "https://" + contentServerName + ":" + contentServerPort, mAccount.getEmail(), contentServerPassword, true, out, null);
if (reply[0].equals("13")) {
fPtr = reply[1].substring(reply[1].indexOf("pointer=") + "pointer=".length(), reply[1].indexOf(", t"));
} else {
postRes = reply[1];
mHandler.post(mUpdateResults);
out.close();
return;
}
}
ECSVideoViewer.java 的代码如下:
public class ECSVideoViewer extends Activity {
private static final String EXTRA_PATH = "path";
/**
* TODO: Set the path variable to a streaming video URL or a local media
* file path.
*/
private static VideoView mVideoView;
public static void actionECSVideoViewer(Context context, Uri uri) {
Intent i = new Intent(context, ECSVideoViewer.class);
i.putExtra(EXTRA_PATH, uri.getEncodedPath());
context.startActivity(i);
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.videoview);
mVideoView = (VideoView) findViewById(R.id.surface_view);
String path = getIntent().getStringExtra(EXTRA_PATH);
mVideoView.setVideoURI(Uri.parse(path));
mVideoView.setMediaController(new MediaController(this));
mVideoView.setOnErrorListener(new OnErrorListener() {
public boolean onError (MediaPlayer mp, int what, int extra) {
mVideoView.getCurrentPosition();
mVideoView.getBufferPercentage();
mVideoView.getDuration();
return true;
}
});
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion (MediaPlayer mp) {
mVideoView.pause();
}
});
mVideoView.requestFocus();
mVideoView.start();
}
public static void resume() {
mVideoView.resume();
}
public static void play() {
mVideoView.start();
}
public static int getCurrentPosition() {
return mVideoView.getCurrentPosition();
}
public static int getBufferPercentage() {
return mVideoView.getBufferPercentage();
}
public static int getDuration() {
return mVideoView.getDuration();
}
public static boolean isPlaying() {
return mVideoView.isPlaying();
}
}
视频开始播放正常,在加载第一个块之后并且正在加载下一个块,但由于某种原因,播放器在尝试读取第二个 1 MB 下载数据块时停止并抛出错误,返回 MEDIA_ERROR_UNKNOWN 和 MEDIA_ERROR_IO . 谁能看到我做错了什么?