Android MediaPlayer/VideoView 错误 (1, -2147483648)

标签 android android-mediaplayer android-videoview

我在从文件路径设置 VideoView 的视频时遇到了不一致的体验。

VideoView myVideoView = findViewById(R.id.videoView);
...
myVideoView.setVideoPath(videoFilename);
...
myVideoView.start();

videoFilename 是我的缓存目录中视频的绝对路径:

String videoFilename = new File(context.getCacheDir(), "myawesomevideo.mp4").getAbsolutePath();

在 Android SDK >= 16 (Jelly Bean) 中,这可以正常工作,并且可以播放我的精彩视频。在 Android 4.0.4 (SDK = 15) 中,调用 myVideoView.start() 时,MediaPlayer 会中断。

错误是永远无益的:

error (1, -2147483648)

我在这里缺少什么?直接从我的包 Assets (res/raw) 或 Internet (http://something.com/myawesomeinternetvideo.mp4) 加载文件,但我不知道如何从缓存目录中读取文件!

最佳答案

事实证明,错误 -2147483648 表示未知错误。这可能与视频编码有关,但也值得检查文件路径是否存在以及 VideoView 是否有权读取它

我的问题是我正在使用 Context.MODE_PRIVATE(默认值)编写文件。

openFileOutput(filename, Context.MODE_PRIVATE);

这表示只有您的应用程序可以访问该文件。我不知 Prop 体如何或为什么,但在 Jelly Bean 及更高版本中,似乎允许视频 View 访问您指定的文件,就好像它是您的应用程序一样,但在 Jelly Bean 之前,视频 View 尝试打开文件在它自己的上下文中(不是你的应用程序的)。由于模式是私有(private)的,所以它失败了。

一种解决方案是使用 Context.MODE_WORLD_READABLE 写入文件。 , 现在已弃用。这表明任何人都可以在该路径打开文件。这显然是不安全且不鼓励的。

我最终创建了一个内容提供程序和我自己的 URI 来处理这种情况。具体来说:

AndroidManfest.xml:

...
    <provider
        android:name="com.myexampleapp.video.VideoProvider"
            android:authorities="com.myexampleapp.video.VideoProvider.files"
        android:exported="false" />
    </application>
</manifest>

VideoProvider.java:

package com.myexampleapp.video;

import java.io.File;
import java.io.FileNotFoundException;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;

public class VideoProvider extends ContentProvider { 
    public static final Uri CONTENT_URI_BASE =
            Uri.parse("content://com.myexampleapp.video.VideoProvider.files.files/");

    private static final String VIDEO_MIME_TYPE = "video/mp4";

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public String getType(final Uri uri) {
        return VIDEO_MIME_TYPE;
    }

    @Override
    public ParcelFileDescriptor openFile(final Uri uri, final String mode)
            throws FileNotFoundException {
        File f = new File(uri.getPath());

        if (f.exists())
            return (ParcelFileDescriptor.open(f,
                    ParcelFileDescriptor.MODE_READ_ONLY));

        throw new FileNotFoundException(uri.getPath());
    }

    @Override
    public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Uri insert(final Uri uri, final ContentValues values) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int update(final Uri uri, final ContentValues values, final String selection, final String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }
}

然后,我在哪里访问我的视频文件:

VideoView myVideoView = findViewById(R.id.videoView);
...
myVideoView.setVideoURI(
    Uri.parse(
        CachedActionProvider.CONTENT_URI_BASE + Uri.encode(videoFilename)));
...
myVideoView.start();

这是告诉 VideoView 向您的 ContentProvider 询问数据的文件描述符的一种非常冗长的方法。文件描述符没有权限,因此您使用应用程序的权限打开文件并将其交给 VideoView,而不是要求 VideoView 使用自己的权限打开文件。

这解决了我的问题,希望也解决了你的问题!

关于Android MediaPlayer/VideoView 错误 (1, -2147483648),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18833537/

相关文章:

Android - 动态更改语言

Android 菜单代码位于单独的类文件中

Android Exoplayer : What is 'playWhenReady' in "onPlayerStateChanged(boolean playWhenReady, int playbackState)" method

Android VideoView RTSP延迟

android - 在 4.0.4 中删除包含 videoView 的 fragment 时出错

java - 通过字符串引用id android

android - HTTP 响应 411 长度要求,Http 客户端 4.0.1 Android

android - 为什么在onCreate之外使用MediaPlayer会导致错误

android - 使用 AssetFileDescriptor 播放音频不起作用

java - MediaController/VideoView 导致 android.view.WindowLeaked