2013-09-16 64 views
23

我一直有不一致的经验,从文件路径设置VideoView的视频。Android MediaPlayer/VideoView错误(1,-2147483648)

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

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

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

在Android SDK中> = 16(果冻豆),这工作得很好,我真棒视频播放。在Android 4.0.4(SDK = 15)中,当调用myVideoView.start()时,MediaPlayer会中断。

的错误是不断无益:

error (1, -2147483648) 

缺少什么我在这里?直接从我的软件包资源(res/raw)或因特网(http://something.com/myawesomeinternetvideo.mp4)加载文件,但我无法弄清楚如何从我的缓存目录中读取文件!

回答

15

事实证明,错误-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使用自己的权限打开文件。

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

+0

你好,我想你的解决方案在视频播放视频view.It起着很好的Android版本4.1,但是当我在模拟器运行此我得到同样的错误'错误(1,-2147483648)'。我已经尝试过.3gp和.mp4视频,但它在模拟器中给我带来了同样的错误。我该怎么做才能解决这个问题,请指导我。这个错误非常模糊,我现在不知道该怎么做。 – Dory

+0

你的模拟器运行什么版本? – spitzanator

+0

我试过版本2.3和4.0 – Dory

4

从缓存目录加载视频文件时,我也遇到了这个问题。这个问题似乎只发生在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)); 
    } 
}