Error de MediaPlayer / VideoView de Android (1, -2147483648)
He estado teniendo una experiencia inconsistente con la fijación de un vídeo de VideoView de una trayectoria del archivo.
VideoView myVideoView = findViewById(R.id.videoView); ... myVideoView.setVideoPath(videoFilename); ... myVideoView.start();
VideoFilename es la ruta absoluta de un video en el directorio de mi caché:
- VideoView getDrawingCache devuelve negro
- Android: ¿Cómo volver a la actividad anterior cuando se detiene el video?
- El botón de retroceso de Android no funciona mientras se reproduce vídeo en VideoView
- Android obtiene la ruta de origen de vídeo de VideoView
- Cómo jugar rtsp live stream desde android? (Rtsp: // someserver: port / live / 001204A006F5.stream)
String videoFilename = new File(context.getCacheDir(), "myawesomevideo.mp4").getAbsolutePath();
En Android SDK> = 16 (Jelly Bean), esto funciona muy bien y mi vídeo impresionante juega. En Android 4.0.4 (SDK = 15), MediaPlayer se rompe cuando se llama a myVideoView.start ().
El error es el siempre inútil:
error (1, -2147483648)
¿Que me estoy perdiendo aqui? Cargando un archivo directamente desde mis recursos de paquete (res / raw) o el Internet ( http://something.com/myawesomeinternetvideo.mp4 ), pero no puedo entender cómo leer los archivos de mi directorio de caché!
- Error de MediaPlayer de Android (1, -2147483648)
- Android - No se pueden reproducir videos (mp4 / mov / 3gp / etc.)?
- ¿El video de Android VideoView almacenó videos en streaming?
- Android VideoView No se puede reproducir el error de vídeo especialmente .mp4
- Reproductor multimedia con YouTube?
- Android WebView transparente en la parte superior de VideoView
- Edición de marcos VideoView de android
- ¿Puede VideoView desmontarse y volver a unirse sin detener el flujo?
Como resultado, el error -2147483648 indica un error desconocido. Esto podría tener algo que ver con la codificación de vídeo, pero también vale la pena comprobar que la ruta del archivo existe y que el VideoView tiene permiso para leerlo .
Mi problema era que estaba escribiendo mis archivos con Context.MODE_PRIVATE (el valor predeterminado).
openFileOutput(filename, Context.MODE_PRIVATE);
Esto indica que sólo su aplicación puede acceder al archivo. No sé específicamente cómo o por qué, pero en Jelly Bean y arriba, parece que la vista de video tiene acceso al archivo que especificas como si fuera tu aplicación, pero antes de Jelly Bean, la vista de video intenta abrir el archivo. Archivo en su propio contexto (no en su aplicación). Dado que el modo es privado, falla.
Una solución es escribir su archivo con Context.MODE_WORLD_READABLE , que ahora está obsoleto. Esto indica que cualquiera puede abrir el archivo en esa ruta. Esto es obviamente inseguro y desalentado.
Terminé creando un proveedor de contenido y mi propio URI para manejar este caso. Específicamente:
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(); } }
Y luego, donde accedo a mis archivos de video:
VideoView myVideoView = findViewById(R.id.videoView); ... myVideoView.setVideoURI( Uri.parse( CachedActionProvider.CONTENT_URI_BASE + Uri.encode(videoFilename))); ... myVideoView.start();
Esta es una manera muy larga de decirle al VideoView que le pida a su ContentProvider el descriptor del archivo a los datos. Los descriptores de archivo no están permitidos, por lo que se abre el archivo utilizando los permisos de la aplicación y se entrega a la VideoView en lugar de pedir a la VideoView para abrir el archivo con sus propios permisos.
Esto soluciona mi problema y espero que el suyo, también!
También tuve este problema al cargar un archivo de vídeo desde el directorio de caché. El problema parecía ocurrir en Nexus-dispositivos solamente pero no puedo probarlo en muchos dispositivos.
Intenté escribir el archivo con Context.MODE_WORLD_READABLE pero esa corrección no funcionó para mí. El VideoProvider.java tampoco lo arregló.
Así que encontré otra solución que funcionó para mí. Creé un tempFile en mi actividad y le di a VideoView el camino de absolut a él.
Tal vez mi código puede ayudar a alguien 🙂
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)); } }
- ¿Cómo consigo que el navegador WVGA Android deje de escalar mis imágenes?
- Cómo establecer el margen dinámicamente en Android?