Android: OutOfMemoryError ao fazer o upload de vídeo - a melhor forma de pedaço ?

? AP257 @ | Original: StackOverFlow
---

Eu tenho o mesmo problema http://stackoverflow.com/questions/1686446/upload-videos-in-android, mas eu vou fornecer mais alguns detalhes . Ao tentar fazer upload de um vídeo no Android, estou lendo -o na memória, e se o vídeo é grande eu recebo um OutOfMemoryError .

Aqui está o meu 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();
}

E aqui está o rastreamento ( o erro é lançado na linha 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

Eu acho que http://stackoverflow.com/questions/1686446/upload-videos-in-android, eu preciso carregá-lo em pedaços . Mas (alerta questão novato ), isso significa que eu deveria fazer várias solicitações PostMethod e cole o arquivo juntos no final de servidor? Ou posso carregar o bytestream na memória em pedaços, e colá -lo em conjunto no código Android?

Se alguém poderia me dar uma pista sobre a melhor abordagem, eu ficaria muito grato .

---

Top 5 Responder

1Jim Blackler @

Você não precisa para obter o arquivo inteiro na memória, em seguida, enviá-lo em uma só vez. Chame connection.getOutputStream () e write () o bytes em blocos.

2Fedor @

Jim Blackler é absolutamente correto . Você não pode ter vídeo completo na memória byte [] . Portanto, você deve ler o arquivo para não byte [ ], mas diretamente para HttpUrlConnectio.getOutputStream ().

Mas, mesmo depois que você ainda vai receber OutOfMemory porque HttpURLConnection armazena todos os dados de saída na memória e envia-lo para a rede apenas quando você está escrevendo completa.

Para substituir esse comportamento você pode usar HttpUrlConnection.setChunkedStreamingMode () ou HttpUrlConnection.setFixedLengthStreamingMode (). Se o seu servidor aceita pedaços de transmissão você pode usar setChunkedStreamingMode (). Caso contrário, você terá que usar setFixedLengthStreamingMode . Para usar setFixedLengthStreamingMode você precisa saber comprimento conteúdo exato antes de iniciar o streaming de dados, por isso é um pouco complicado .

Não mais OutOfMemory neste momento.

Se você tem o vídeo em arquivo, você pode escolher uma outra abordagem, muito mais simples. Use HttpClient e FileBody assim http://stackoverflow.com/questions/3038409/how-to-send-http-post-request-and-recieve-response/3038747#3038747 . Eu acho que eles implementar todos os métodos acima e você não terá que se preocupar com isso .

3Anthony @

Apenas uma pequena nota :

O setChunkedStreamingMode e setFixedeLengthStreamingMode não funcionam no android 2.1, Eles trabalham perfeito em 2.0 e 2.2

4Rags @

O seu melhor para dividir o arquivo em partes e fazer o upload . Mesclar as partes no lado do servidor.