2013-09-16 21 views
23

Ich habe eine inkonsistente Erfahrung mit der Einstellung eines VideoView-Videos aus einem Dateipfad gemacht.Android MediaPlayer/VideoView-Fehler (1, -2147483648)

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

videoFilename ist der absolute Pfad eines Videos in meinem Cache-Verzeichnis:

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

In Android SDK> = 16 (Jelly Bean), das funktioniert ganz gut und mein geiles Video spielt. In Android 4.0.4 (SDK = 15) bricht der MediaPlayer beim Aufruf von myVideoView.start() ab.

Der Fehler ist die immer wenig hilfreich:

error (1, -2147483648) 

Was ich hier fehlt? Laden einer Datei direkt aus meinen Paket-Assets (res/raw) oder dem Internet (http://something.com/myawesomeinternetvideo.mp4), aber ich kann nicht herausfinden, wie man Dateien aus meinem Cache-Verzeichnis liest!

Antwort

15

Wie sich herausstellt, zeigt der Fehler -2147483648 einen unbekannten Fehler an. Dies könnte etwas mit der Videokodierung zu tun haben, aber es lohnt sich auch zu überprüfen, ob der Dateipfad existiert und dass der VideoView die Berechtigung hat, ihn zu lesen.

Mein Problem war, dass ich meine Dateien mit Context.MODE_PRIVATE (der Standard) schrieb.

openFileOutput(filename, Context.MODE_PRIVATE); 

Dies zeigt an, dass nur Ihre Anwendung auf die Datei zugreifen kann. Ich weiß nicht genau, wie oder warum, aber in Jelly Bean und darüber scheint es, dass die Videoansicht auf die von Ihnen angegebene Datei zugreifen kann, als wäre es Ihre Anwendung, aber vor Jelly Bean versucht die Videoansicht, die Datei in einem eigenen Kontext (nicht der Ihrer Anwendung). Da der Modus privat ist, schlägt er fehl.

Eine Lösung besteht darin, Ihre Datei mit Context.MODE_WORLD_READABLE zu schreiben, die jetzt veraltet ist. Dies zeigt an, dass jeder die Datei unter diesem Pfad öffnen kann. Dies ist offensichtlich unsicher und entmutigt.

Ich habe einen Inhaltsanbieter und meine eigene URI erstellt, um diesen Fall zu behandeln. Im Einzelnen:

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

Und dann, wo ich meine Videodateien zuzugreifen:

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

Diese ist echt langweilige Möglichkeit, dem VideoView mitzuteilen, dass Sie Ihren ContentProvider nach dem Dateideskriptor für die Daten fragen sollen. Dateideskriptoren sind nicht berechtigt, daher öffnen Sie die Datei mit den Berechtigungen Ihrer App und geben sie an die Videoansicht weiter, anstatt die Videoansicht zu bitten, die Datei mit ihren eigenen Berechtigungen zu öffnen.

Das behebt mein Problem und hoffentlich auch Ihnen!

+0

Hallo, ich Ihre Lösung versucht Video in Video spielen view.It spielt auch in Android-Version 4.1, aber wenn ich diese laufen in Emulatoren ich bin immer gleichen Fehler 'Fehler (1, -2147483648)'. Ich habe .3gp und .mp4 Videos versucht, aber es gibt mir denselben Fehler in den Emulatoren. Was soll ich tun, um dieses Problem zu lösen, bitte führen Sie mich. Dieser Fehler ist sehr vage, ich verstehe nicht, was ich jetzt tun soll. – Dory

+0

In welchen Versionen laufen Ihre Emulatoren? – spitzanator

+0

Ich versuchte in der Version 2.3 und auch in 4.0 – Dory

4

Ich hatte auch dieses Problem beim Laden einer Videodatei aus dem Cache-Verzeichnis. Das Problem schien nur auf Nexus-Geräten zu liegen, aber ich konnte es nicht auf vielen Geräten testen.

Ich habe versucht, die Datei mit Context.MODE_WORLD_READABLE zu schreiben, aber diese Korrektur funktionierte nicht für mich. Der VideoProvider.java hat es auch nicht repariert.

So fand ich eine andere Lösung, die für mich funktionierte. Ich habe eine tempFile in meiner Activity erstellt und dem VideoView den absoluten Pfad dazu gegeben.

Vielleicht kann mein Code jemand helfen :)

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)); 
    } 
} 
Verwandte Themen