Android lecteur multimédia/VideoView erreur (1, -2147483648)

j'ai eu une expérience incohérente avec la configuration D'une vidéo de VideoView à partir d'un chemin de fichier.

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

videoFilename est le chemin absolu d'une vidéo dans mon répertoire cache:

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

dans Android SDK >= 16 (Jelly Bean), cela fonctionne très bien et ma vidéo impressionnante joue. Dans Android 4.0.4 (SDK = 15), Le MediaPlayer se casse lorsque myVideoView.start() est appelé.

L'erreur est toujours utile:

error (1, -2147483648)

Ce qui me manque ici? Chargement d'un fichier directement depuis mon package assets (res / raw) ou internet (http://something.com/myawesomeinternetvideo.mp4), mais je ne peux pas comprendre comment lire des fichiers à partir de mon répertoire cache!

23
demandé sur spitzanator 2013-09-16 21:05:07

2 réponses

il s'avère Que l'erreur de -2147483648 indique une erreur inconnue. Cela pourrait avoir quelque chose à voir avec l'encodage de la vidéo, mais cela vaut aussi la peine de vérifier que le chemin du fichier existe et que le VideoView a l'autorisation de le lire.

mon problème était que j'écrivais mes dossiers avec Contexte.MODE_PRIVATE (la valeur par défaut).

openFileOutput(filename, Context.MODE_PRIVATE);

indique que seule votre application peut accéder au fichier. Je ne sais pas exactement comment ou pourquoi, mais dans Jelly Bean et ci-dessus, il semble que la vue vidéo est autorisée à accéder au fichier que vous spécifiez comme si c'était votre application, mais avant Jelly Bean, la vue vidéo essaie d'ouvrir le fichier dans son propre contexte (pas celui de votre application). Comme le mode est privé, il échoue.

Une solution est d'écrire votre fichier avec Contexte.MODE_WORLD_READABLE, qui est maintenant obsolète. Cela indique que n'importe qui peut ouvrir le fichier chemin d'accès. C'est évidemment dangereux et décourager.

j'ai fini par créer un fournisseur de contenu et mon propre URI pour gérer cette affaire. Plus précisément:

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

Et puis, où j'ai accès à mes fichiers vidéo:

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

C'est une façon très longue de dire à VideoView de demander à votre ContentProvider le descripteur de fichier des données. Les descripteurs de fichiers ne sont pas autorisés, donc vous ouvrez le fichier en utilisant les permissions de votre application et vous le donnez à VideoView plutôt que de demander à VideoView d'ouvrir le fichier en utilisant ses propres permissions.

Cela résout mon problème et j'espère le vôtre, aussi!

15
répondu spitzanator 2013-09-16 17:05:07

j'ai aussi eu ce problème lors du chargement d'un fichier vidéo depuis le répertoire cache. Le problème a semblé se produire sur Nexus-dispositifs seulement, mais je n'ai pas compté le tester sur beaucoup de dispositifs.

j'ai essayé d'écrire le fichier avec le Contexte.MODE_WORLD_READABLE mais ce correctif n'a pas fonctionné pour moi. Le VideoProvider.java ne l'a pas réparé non plus.

alors j'ai trouvé une autre solution qui a fonctionné pour moi. J'ai créé un fichier tempFile dans mon activité et j'ai donné à VideoView le chemin absolut il.

Peut-être que mon code peut aider quelqu'un :)

 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));
    }
}
4
répondu Maik Peschutter 2015-03-25 11:07:36