【问题标题】:Android MediaPlayer/VideoView error (1, -2147483648)Android MediaPlayer/VideoView 错误 (1, -2147483648)
【发布时间】:2013-09-20 22:17:27
【问题描述】:

我在从文件路径设置 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)

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

【问题讨论】:

    标签: android android-mediaplayer android-videoview


    【解决方案1】:

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

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

    openFileOutput(filename, Context.MODE_PRIVATE);
    

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

    一种解决方案是使用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 版本 4.1 中运行良好,但是当我在模拟器中运行它时,我收到相同的错误 Error (1,-2147483648)。我尝试过 .3gp 和 .mp4 视频,但它在模拟器中给了我同样的错误。我该怎么做才能解决这个问题,请指导我。这个错误真的很模糊,我现在不知道该怎么办。
    • 你的模拟器运行的是什么版本?
    • 我在模拟器上播放视频时遇到了一些严重的问题,无论版本如何。我不相信它们可以指示真实设备上会发生什么。 Android 4.1 是您唯一的设备吗?
    • 是的,我的设备版本是 4.1,视频在其中播放良好。但在另一个 2.2 版的设备上,视频无法播放。
    • 您可以在图库等媒体应用中播放相同的视频吗?我也发现了一些手机解码问题。
    【解决方案2】:

    我在从缓存目录加载视频文件时也遇到了这个问题。这个问题似乎只发生在 Nexus 设备上,但我无法在很多设备上进行测试。

    我尝试使用 Context.MODE_WORLD_READABLE 编写文件,但该修复对我不起作用。 VideoProvider.java 也没有修复它。

    所以我找到了另一个适合我的解决方案。我在我的 Activity 中创建了一个 tempFile,并为 VideoView 提供了它的绝对路径。

    也许我的代码可以帮助某人:)

     private MediaController mController;
    
    private VideoView mVideoView;
    
    private File mTmpFile = null;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video);
    
        init();
    }
    
    private void init() {
        mProgressDialog = new ProgressDialog(this);
    
        mVideoView = (VideoView) findViewById(R.id.surface_video);
        mVideoView.requestFocus();
        mController = new MediaController(this);
        mVideoView.setMediaController(mController);
    
        mVideoView.setOnPreparedListener(this);
        mVideoView.setOnCompletionListener(this);
        mVideoView.setOnErrorListener(this);
    
        String url = getIntent().getExtras().getString(MainActivity.VIDEO_URL_EXTRA_KEY);
        if (VideoLoaderTask.hasVideo(this, url)) {
            url = getCacheDir().toString().concat("/" + VideoLoaderTask.VIDEO_DIR + "/").concat(url);
            copyToTmpFile(url);
            mVideoView.setVideoPath(mTmpFile.getAbsolutePath());
        } else {
            mVideoView.setVideoURI(Uri.parse(url));
        }
    
        mProgressDialog.show();
        mVideoView.start();
    }
    
    @Override
    public void onDestroy() {
        if (mTmpFile != null) {
            mTmpFile.delete();
        }
        super.onDestroy();
    }
    
    private void copyToTmpFile(String url) {
        File f = new File(url);
        try {
            mTmpFile = File.createTempFile("video", null);
            mTmpFile.deleteOnExit();
    
            FileInputStream is = new FileInputStream(f);
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
    
            FileOutputStream fos = new FileOutputStream(mTmpFile);
            fos.write(buffer);
            fos.close();
        } catch (Exception e) {
            mVideoView.setVideoURI(Uri.parse(url));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-17
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多