Android: OutOfMemoryError al subir video - la mejor forma de trozo ?

? AP257 @ | Original: StackOverFlow
---

Tengo el mismo problema http://stackoverflow.com/questions/1686446/upload-videos-in-android, pero voy a proporcionar algunos detalles más . Al tratar de subir un video en Android, lo estoy leyendo en la memoria, y si el video es grande Puedo obtener 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 de 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 http://stackoverflow.com/questions/1686446/upload-videos-in-android, tengo que subirlo en trozos. Pero ( alerta pregunta novato ) ¿significa que debo hacer múltiples peticiones PostMethod y pegar el archivo junto al final del servidor ? O puedo cargar la corriente de bytes en la memoria en trozos, y la cola juntos en el código de Android?

Si alguien me puede dar una pista sobre el mejor enfoque, yo estaría muy agradecido .

---

Top 5 Respuesta

1Jim Blackler @

Usted no necesita obtener el archivo completo en la memoria, y luego subirlo a una sola vez. Llame connection.getOutputStream () y write () los bytes en trozos.

2Fedor @

Jim Blackler es absolutamente correcto. No se puede tener video completo en la memoria en el byte [ ] . Así que usted debe leer el archivo no byte [ ], sino directamente a HttpUrlConnectio.getOutputStream ().

Pero incluso después de que usted todavía consigue OutOfMemory porque HttpURLConnection cachés todos los datos de salida en la memoria y lo envía a la red sólo cuando estás escritura completa .

Para cambiar este comportamiento, puede utilizar HttpUrlConnection.setChunkedStreamingMode () o HttpUrlConnection.setFixedLengthStreamingMode (). Si el servidor acepta trozos corriente puede utilizar setChunkedStreamingMode (). De lo contrario, tendrá que usar setFixedLengthStreamingMode . Para utilizar setFixedLengthStreamingMode usted necesita saber la longitud contenido exacto antes de comenzar streaming de datos, así que es un poco complicado .

No más OutOfMemory en este punto.

Si tienes un video en el archivo se puede elegir otro enfoque, mucho más simple. Utilice HttpClient y FileBody así http://stackoverflow.com/questions/3038409/how-to-send-http-post-request-and-recieve-response/3038747#3038747 . Creo que poner en práctica todos los métodos arriba y no tendrás que preocuparte por eso.

3Anthony @

Sólo una pequeña nota :

El setChunkedStreamingMode y setFixedeLengthStreamingMode no funcionan en Android 2.1, Trabajan perfecto en 2.0 y 2.2

4Rags @

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