Android: OutOfMemoryError durante la subida de video – la mejor manera de chunk?

Tengo el mismo problema que se describe aquí , pero voy a proporcionar algunos detalles más. Mientras intento cargar un video en Android, lo estoy leyendo en memoria, y si el video es grande consigo un OutOfMemoryError.

Aquí está mi código:

// get bytestream to upload videoByteArray = getBytesFromFile(cR, fileUriString); public static byte[] getBytesFromFile(ContentResolver cR, String fileUriString) throws IOException { Uri tempuri = Uri.parse(fileUriString); InputStream is = cR.openInputStream(tempuri); byte[] b3 = readBytes(is); is.close(); return b3; } public static byte[] readBytes(InputStream inputStream) throws IOException { ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); // this is storage overwritten on each iteration with bytes int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int len = 0; while ((len = inputStream.read(buffer)) != -1) { byteBuffer.write(buffer, 0, len); } return byteBuffer.toByteArray(); } 

Y aquí está el rastreo (el error se lanza en la línea byteBuffer.write(buffer, 0, len) ):

 04-08 11:56:20.456: ERROR/dalvikvm-heap(6088): Out of memory on a 16775184-byte allocation. 04-08 11:56:20.456: INFO/dalvikvm(6088): "IntentService[UploadService]" prio=5 tid=17 RUNNABLE 04-08 11:56:20.456: INFO/dalvikvm(6088): | group="main" sCount=0 dsCount=0 s=N obj=0x449a3cf0 self=0x38d410 04-08 11:56:20.456: INFO/dalvikvm(6088): | sysTid=6119 nice=0 sched=0/0 cgrp=default handle=4010416 04-08 11:56:20.456: INFO/dalvikvm(6088): at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:~93) 04-08 11:56:20.456: INFO/dalvikvm(6088): at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:218) 04-08 11:56:20.456: INFO/dalvikvm(6088): at com.android.election2010.UploadService.readBytes(UploadService.java:199) 04-08 11:56:20.456: INFO/dalvikvm(6088): at com.android.election2010.UploadService.getBytesFromFile(UploadService.java:182) 04-08 11:56:20.456: INFO/dalvikvm(6088): at com.android.election2010.UploadService.doUploadinBackground(UploadService.java:118) 04-08 11:56:20.456: INFO/dalvikvm(6088): at com.android.election2010.UploadService.onHandleIntent(UploadService.java:85) 04-08 11:56:20.456: INFO/dalvikvm(6088): at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:30) 04-08 11:56:20.456: INFO/dalvikvm(6088): at android.os.Handler.dispatchMessage(Handler.java:99) 04-08 11:56:20.456: INFO/dalvikvm(6088): at android.os.Looper.loop(Looper.java:123) 04-08 11:56:20.456: INFO/dalvikvm(6088): at android.os.HandlerThread.run(HandlerThread.java:60) 04-08 11:56:20.467: WARN/dalvikvm(6088): threadid=17: thread exiting with uncaught exception (group=0x4001b180) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): Uncaught handler: thread IntentService[UploadService] exiting due to uncaught exception 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): java.lang.OutOfMemoryError 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:93) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:218) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at com.android.election2010.UploadService.readBytes(UploadService.java:199) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at com.android.election2010.UploadService.getBytesFromFile(UploadService.java:182) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at com.android.election2010.UploadService.doUploadinBackground(UploadService.java:118) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at com.android.election2010.UploadService.onHandleIntent(UploadService.java:85) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:30) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at android.os.Handler.dispatchMessage(Handler.java:99) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at android.os.Looper.loop(Looper.java:123) 04-08 11:56:20.467: ERROR/AndroidRuntime(6088): at android.os.HandlerThread.run(HandlerThread.java:60) 04-08 11:56:20.496: INFO/Process(4657): Sending signal. PID: 6088 SIG: 3 

Supongo que como @DroidIn sugiere , necesito cargarlo en trozos. Pero (alerta de pregunta de novato) que significa que debo hacer varias solicitudes PostMethod, y pegar el archivo juntos en el extremo del servidor? ¿O puedo cargar el bytestream en memoria en trozos y pegarlo en el código de Android?

Si alguien pudiera darme una pista sobre el mejor enfoque, estaría muy agradecido.

Jim Blackler es absolutamente correcto. No se puede tener vídeo completo en memoria en byte []. Por lo que debe leer el archivo no a byte [] pero directamente a HttpUrlConnectio.getOutputStream ().

Pero incluso después de que usted todavía obtendrá OutOfMemory porque HttpUrlConnection almacena en caché todos los datos de salida en la memoria y lo envía a la red sólo cuando se escribe por completo.

Para anular este comportamiento puede utilizar HttpUrlConnection.setChunkedStreamingMode () o HttpUrlConnection.setFixedLengthStreamingMode (). Si su servidor acepta fragmentos de flujo, puede utilizar setChunkedStreamingMode (). De lo contrario, tendrá que utilizar setFixedLengthStreamingMode. Para usar setFixedLengthStreamingMode necesitará saber la longitud exacta del contenido antes de iniciar la transmisión de datos, por lo que es un poco complicado.

No más OutOfMemory en este punto.

Si tienes tu video en archivo puedes elegir otro enfoque, mucho más simple. Utilice HttpClient y FileBody así ¿Cómo enviar HTTP POST solicitud y recibir respuesta? . Creo que implementar todos los métodos anteriores y no tendrá que preocuparse por eso.

No necesita obtener todo el archivo en la memoria y luego subirlo de una vez. Llame a connection.getOutputStream () y escriba () los bytes en trozos.

Sólo una pequeña nota:

El setChunkedStreamingMode y setFixedeLengthStreamingMode NO funcionan en android 2.1, Funcionan perfectos en 2.0 y 2.2

Es mejor dividir el archivo en partes y subir. Combinar las partes en el lado del servidor.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.