Android MediaPlayer/VideoView 错误 (1, -2147483648) [英] Android MediaPlayer/VideoView error (1, -2147483648)

查看:32
本文介绍了Android MediaPlayer/VideoView 错误 (1, -2147483648)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been having an inconsistent experience with setting a VideoView's video from a file path.

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

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

videoFilename is the absolute path of a video in my cache directory:

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

在 Android SDK >= 16 (Jelly Bean) 中,这很好用,我的精彩视频也能播放.在 Android 4.0.4 (SDK = 15) 中,调用 myVideoView.start() 时 MediaPlayer 会中断.

In Android SDK >= 16 (Jelly Bean), this works just fine and my awesome video plays. In Android 4.0.4 (SDK = 15), the MediaPlayer breaks when myVideoView.start() is called.

错误是无益的:

error (1, -2147483648)

我在这里错过了什么?直接从我的包资产 (res/raw) 或互联网 (http://something.com/myawesomeinternetvideo.mp4) 加载文件.mp4),但我不知道如何从缓存目录中读取文件!

What am I missing here? Loading a file directly from my package assets (res/raw) or the internet (http://something.com/myawesomeinternetvideo.mp4), but I can't figure out how to read files out of my cache directory!

推荐答案

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

As it turns out, error -2147483648 indicates an unknown error. This could have something to do with the video encoding, but it's also worth checking that the file path exists and that the VideoView has permission to read it.

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

My issue was that I was writing my files with Context.MODE_PRIVATE (the default).

openFileOutput(filename, Context.MODE_PRIVATE);

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

This indicates that only your application can access the file. I don't know specifically how or why, but in Jelly Bean and above, it appears that the video view is allowed to access the file you specify as if it were your application, but before Jelly Bean, the video view tries to open the file in its own context (not your application's). Since the mode is private, it fails.

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

One solution is to write your file with Context.MODE_WORLD_READABLE, which is now deprecated. This indicates that anyone can open the file at that path. This is obviously unsafe and discouraged.

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

I ended up creating a content provider and my own URI to handle this case. Specifically:

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

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

And then, where I access my video files:

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

这是告诉 VideoView 向您的 ContentProvider 询问数据的文件描述符的一种非常冗长的方式.文件描述符未经许可,因此您可以使用应用的权限打开文件并将其交给 VideoView,而不是要求 VideoView 使用其自己的权限打开文件.

This is a really long-winded way of telling the VideoView to ask your ContentProvider for the file descriptor to the data. File descriptors aren't permissioned, so you open the file using your app's permissions and hand it off to the VideoView rather than asking the VideoView to open the file using its own permissions.

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

This fixes my issue and hopefully yours, too!

这篇关于Android MediaPlayer/VideoView 错误 (1, -2147483648)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆