2

目前我正在开发一个应用程序,该应用程序应该将视频下载到其内部存储中(不幸的是他们没有 sd 卡)并简单地播放它们。到目前为止我尝试过的是:

标准 VideoView,将 /data/data/.../file.mp4 设置为路径 - 不起作用。使用带有 SurfaceView 的 MediaPlayer,使用路径或文件描述符 - 不起作用。

我现在在这里有一个稍微修改过的 VideoView 版本,它有以下变化:

        if(mUri != null)
        {
            mMediaPlayer.setDataSource(mContext, mUri);
        }
        else
        {
            mMediaPlayer.setDataSource(mFd);
        }

还有一个 setFD 方法允许我设置我的文件描述符。这比将整个 MediaPlayer/SurfaceView 放入我的活动更容易和更清洁 - imo。问题如下:

内部存储中的文件是这样创建的:

                FileInputStream fis = openFileInput(Downloader.TMP_FILENAME);
                FileOutputStream fos = openFileOutput(Downloader.FILENAME
                        + ext, Context.MODE_WORLD_READABLE);
                byte[] buf = new byte[2048];
                while (fis.read(buf) > 0) {
                    fos.write(buf);
                }
                fis.close();
                fos.close();
                deleteFile(Downloader.TMP_FILENAME);
                Log.d(TAG, "Replacement done!");

基本上它正在读取一个临时文件(因为我不想覆盖当前播放的文件..但这并不重要)并将其(在 onCompletion 之后)写入新文件,然后删除临时文件。

到目前为止,我已经在 3 种不同的 Android 版本和设备上对其进行了测试: - 装有 Android 2.2 的平板电脑 - 装有 Android 4.2 的 Nexus 7 - 装有 Android 4.1.2 的 HTC Sensation

它根本不起作用。它播放可以说视频的前 100 毫秒,包括。声音然后弹出一个弹出窗口,logcat告诉我:

12-19 14:33:48.074: W/MediaPlayer(5560): info/warning (3, 0)
12-19 14:33:48.074: I/MediaPlayer(5560): Info (3,0)
12-19 14:33:48.394: E/MediaPlayer(5560): error (1, -1007)
12-19 14:33:48.394: E/MediaPlayer(5560): Error (1,-1007)

但我真的不知道这应该是什么意思。我在整个互联网上搜索它,我发现的只是“使用 WORLD_READABLE,它会解决问题!” 或“只使用文件描述符,似乎不在乎权限!”。但对我来说,它不起作用。

我真的很感激任何帮助。

编辑:

            FileInputStream fid = new FileInputStream((getFilesDir() + "/"
                    + Downloader.FILENAME + ext)));

            mVideoView.setVideoFD(fid.getFD());

This is how I add the File Descriptor to the MediaPlayer.

After reencoding the file, this is what I get:

12-19 15:06:45.664: E/MediaPlayer(7616): Unable to to create media player
12-19 15:06:45.664: W/System.err(7616): java.io.IOException: setDataSourceFD failed.: status=0x80000000
12-19 15:06:45.664: W/System.err(7616):     at android.media.MediaPlayer.setDataSource(Native Method)
12-19 15:06:45.664: W/System.err(7616):     at android.media.MediaPlayer.setDataSource(MediaPlayer.java:976)

This is how I download it from my webserver:

Log.i(TAG, "Opening remote connection to " + mFile.getHost()
                + mFile.getPath());
        URLConnection c = mFile.openConnection();
        c.connect();
        final long lastModified = c.getLastModified();
        final String mExtension;
        if (c.getHeaderField("Content-Disposition") != null) {
            final String mFilename = c
                    .getHeaderField("Content-Disposition").split("=")[1];
            Log.i("Downloader", "Filename is " + mFilename
                    + ", split length is " + mFilename.split("\\.").length);
            mExtension = mFilename.split("\\.")[mFilename
                    .split("\\.").length - 1];
        } else {
            mExtension = "mp4";
        }

        InputStream is = c.getInputStream();

        Log.i(TAG, "Creating temporary local file");
        // create local temporary file
        FileOutputStream fos = mContext.openFileOutput(TMP_FILENAME,
                Context.MODE_WORLD_READABLE);

        // start reading
        byte[] buf = new byte[BUFFER_SIZE];
        int bytesRead = 0;
        int curRead = 0;
        Log.i(TAG, "Starting download.. to " + TMP_FILENAME);
        if (mDownloadChangeListener != null)
            mDownloadChangeListener.onDownloadStart();

        while ((curRead = is.read(buf)) > -1) {
            fos.write(buf);
            bytesRead += curRead;
        }
        Log.i(TAG, "Read " + bytesRead + " bytes in total.");
        Log.i(TAG, "Download finished!");
        // end of stream, tell app to rename file.
        if (mDownloadChangeListener != null)
            mDownloadChangeListener.onDownloadFinished(TMP_FILENAME,
                    mExtension);

        is.close();
        fos.close();

After downloading it, on the onDownloadFinished listener, I execute the following code:

                FileInputStream fis = openFileInput(Downloader.TMP_FILENAME);
                FileOutputStream fos = openFileOutput(Downloader.FILENAME
                        + ext, Context.MODE_WORLD_WRITEABLE);
                byte[] buf = new byte[2048];
                while (fis.read(buf) > 0) {
                    fos.write(buf);
                }
                fis.close();
                fos.close();
                deleteFile(Downloader.TMP_FILENAME);
                Log.d(TAG, "Replacement done!");

Any ideas what could possibly go wrong? My only other idea would be that it's because of the internal storage-thing.. but the error message says something else?

4

2 回答 2

2

Error -1007 stands for MEDIA_ERROR_MALFORMED. It means that the file you're trying to play doesn't conform to the file specification put down in the official documentation. Something is either wrong with the media you're receiving, or in your method of saving it.

Personally, your method of saving it looks fine to me, so I'm guessing that the source file itself is the problem.

于 2012-12-19T13:55:38.617 回答
2

Found the solution. Every way I've tested worked probably, because all errors I received came from "wrong downloaded media files"...

while((curRead = in.read(buf)) {
   out.write(buf);
}

Was simply missing a ",0 ,curRead" - all working now. It's obviously because read() can always return less than BUFFER_SIZE and then writes 0-bytes into the rest or something...

Thanks!

于 2012-12-19T19:05:09.927 回答