Ошибка Android MediaPlayer / VideoView (1, -2147483648)

У меня был непоследовательный опыт установки видео VideoView из пути к файлу.

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

VideoFilename – это абсолютный путь видео в моем каталоге кеша:

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

В Android SDK> = 16 (Jelly Bean) это работает отлично, и мое потрясающее видео играет. В Android 4.0.4 (SDK = 15) MediaPlayer прерывается при вызове myVideoView.start ().

Ошибка всегда бесполезна:

 error (1, -2147483648) 

Что мне здесь не хватает? Загрузка файла непосредственно из моих активов пакета (res / raw) или в интернет ( http://something.com/myawesomeinternetvideo.mp4 ), но я не могу понять, как читать файлы из моего каталога кеша!

Solutions Collecting From Web of "Ошибка Android MediaPlayer / VideoView (1, -2147483648)"

Как оказалось, ошибка -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 открыть файл, используя свои собственные разрешения.

Это исправляет мою проблему и, надеюсь, и вашу!

У меня также была эта проблема при загрузке видеофайла из каталога cache. Проблема, казалось, возникала только на устройствах 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)); } }