1

我正在将 MP4 文件从 Web 应用程序下载到移动设备上的文件中。由于文件往往很大,我想在获得一些数据后立即开始播放,而不是等到整个文件下载完毕,所以我想出了以下方案:

  1. 将前 1 MB 的数据下载到我的 SD 卡上的文件中。
  2. 启动视频播放器。
  3. 以 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 . 谁能看到我做错了什么?

4

0 回答 0