【问题标题】:Android, VideoView, Internal StorageAndroid、VideoView、内部存储
【发布时间】:2012-12-19 13:50:42
【问题描述】:

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

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

我现在在这里是稍微修改过的 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 - HTC Sensation 与 Android 4.1.2

它根本不起作用。它播放可以说视频的前 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());

这就是我将文件描述符添加到 MediaPlayer 的方式。

重新编码文件后,这是我得到的:

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)

这是我从我的网络服务器下载它的方式:

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();

下载后,在 onDownloadFinished 监听器上,我执行如下代码:

                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!");

有什么想法可能会出错吗?我唯一的另一个想法是这是因为内部存储的东西..但是错误消息说的是别的东西?

【问题讨论】:

    标签: android permissions media-player android-videoview file-descriptor


    【解决方案1】:

    错误-1007 代表MEDIA_ERROR_MALFORMED。这意味着您尝试播放的文件不符合官方文档中的文件规范。您收到的媒体有问题,或者您的保存方法有问题。

    就我个人而言,你保存它的方法对我来说看起来不错,所以我猜测源文件本身就是问题所在。

    【讨论】:

    • 感谢您的回答。这就是我从互联网上下载它的方式: URLConnection c = mFile.openConnection(); c.connect(); InputStream = c.getInputStream();然后简单地读/写到另一个 Stream.. 我会尝试重新编码它以匹配 Android 标准,即使我认为我已经这样做了。
    • Mh 不确定是不是因为我重新编码了示例文件,但现在我得到:12-19 15:06:45.664: W/System.err(7616): java.io。 IOException:setDataSourceFD 失败。:status=0x80000000
    • 这似乎是一个常见错误,也与文件格式有关:stackoverflow.com/questions/9657280/…stackoverflow.com/questions/9625680/…
    • 嗯,我不确定为什么它不接受我的文件。我查看了“允许的”编解码器developer.android.com/guide/appendix/media-formats.html,尝试了 MPEG-4/MP3 组合,但没有奏效。我在 Ubuntu 上,我真的不知道应该如何编码我的视频以及使用哪个编解码器
    • 您的文件头可能有问题。看看您是否可以从某个开源项目中找到标准或演示视频文件并尝试使用它。
    【解决方案2】:

    找到了解决办法。我测试过的每一种方法都可能有效,因为我收到的所有错误都来自“错误下载的媒体文件”......

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

    只是缺少一个“,0 ,curRead” - 现在一切正常。这显然是因为 read() 总是可以返回小于 BUFFER_SIZE 然后将 0 字节写入其余部分......

    谢谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多