2013-09-16 66 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)); 
    } 
}