2013-09-16 15 views
23

ファイルパスからVideoViewのビデオを設定する際に矛盾した経験をしています。Android MediaPlayer/VideoViewエラー(1、-2147483648)

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

videoFilenameは私のキャッシュディレクトリ内の映像の絶対パスです:AndroidのSDK> = 16(ジェリービーン)で

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

、これはうまく動作し、私の素晴らしいビデオが再生されます。 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の前には、ビデオビューでファイルを自分のコンテキスト(アプリケーションのものではない)に保存します。モードはプライベートなので、失敗します。

解決策の1つは、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(); 

この本物ですあなたのContentProviderにファイル記述子のデータを要求するようVideoViewに伝えています。ファイル記述子は許可されていないため、アプリケーションのアクセス権を使用してファイルを開き、VideoViewに独自のアクセス権を使用してファイルを開くように要求するのではなく、VideoViewに渡します。

これは私の問題とうまくいけばあなたのものも修正します!

+0

を助けることができる、私はアンドロイドのバージョン4.1でよく果たしているview.Itビデオでビデオを再生するにはあなたのソリューションを試してみましたが、私はエミュレータでこれを実行すると私は同じエラーを取得しています'エラー(1、-2147483648)。 .3gpと.mp4ビデオを試しましたが、エミュレータで同じエラーが表示されます。この問題を解決するにはどうすればいいですか、私を案内してください。このエラーは本当にあいまいです。私は今何をすべきかを知りません。 – Dory

+0

エミュレータはどのバージョンを実行していますか? – spitzanator

+0

私はバージョン2.3でも4.0でも試しました – Dory

4

また、cache-directoryからビデオファイルをロードする際にこの問題が発生しました。問題はNexusデバイスでしか発生していないようでしたが、多くのデバイスでそれをテストしていませんでした。

私はContext.MODE_WORLD_READABLEでファイルを書き込もうとしましたが、その修正がうまくいきませんでした。 VideoProvider.javaもそれを修正しませんでした。

私は私のために働く他の解決策を見つけました。私は自分のアクティビティで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)); 
    } 
} 
関連する問題