Android : OutOfMemoryError durante il caricamento di video - il modo migliore per pezzo ?

? AP257 @ | Original: StackOverFlow

Ho lo stesso problema http://stackoverflow.com/questions/1686446/upload-videos-in-android, ma io fornirò qualche dettaglio in più . Durante il tentativo di caricare un video in Android, lo sto leggendo in memoria, e se il video è grande io ottenere un OutOfMemoryError .

Ecco il mio codice :

// 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();
}

Ed ecco il traceback ( l'errore è gettato sul byteBuffer.write(buffer, 0, len) linea ) :

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

Immagino che http://stackoverflow.com/questions/1686446/upload-videos-in-android, ho bisogno di caricarlo in pezzi . Ma ( newbie alert questione) vuol dire che avrei dovuto fare più richieste PostMethod, e incollare il file insieme alla fine del server ? O posso caricare la bytestream in memoria in blocchi, e la colla insieme nel codice Android ?

Se qualcuno mi potrebbe dare un indizio per l'approccio migliore, sarei molto grato .

Top 5 Risposta

1Jim Blackler @

Non è necessario per ottenere l'intero file in memoria, poi caricarlo su un colpo . Chiamare connection.getOutputStream ( ) e write () i byte in blocchi .

2Fedor @

Jim Blackler è assolutamente corretto . Non si può avere il video completo in memoria in byte [ ] . Così si dovrebbe leggere file non byte [ ] ma direttamente a HttpUrlConnectio.getOutputStream ( ) .

Ma anche dopo che ci si può comunque OutOfMemory perché HttpURLConnection memorizza nella cache tutti i dati di output in memoria e lo invia alla rete solo quando si è iscritto completo .

Per ignorare questo comportamento è possibile utilizzare HttpUrlConnection.setChunkedStreamingMode ( ) o HttpUrlConnection.setFixedLengthStreamingMode ( ) . Se il server accetta blocchi flusso si può usare setChunkedStreamingMode ( ) . Altrimenti dovrete usare setFixedLengthStreamingMode . Per utilizzare setFixedLengthStreamingMode avrete bisogno di sapere esattamente la lunghezza del contenuto prima di avviare lo streaming di dati, quindi è un po 'difficile .

Non più OutOfMemory a questo punto.

Se avete il vostro video nel file è possibile scegliere un altro approccio, molto più semplice . Utilizzare HttpClient e FileBody genere http://stackoverflow.com/questions/3038409/how-to-send-http-post-request-and-recieve-response/3038747#3038747 . Penso che implementare tutti i metodi di cui sopra e non dovrete preoccuparvi di questo.

3Anthony @

Solo una piccola nota :

Il setChunkedStreamingMode e setFixedeLengthStreamingMode non funzionano in Android 2.1, Lavorano perfetta in 2.0 e 2.2

4Rags @

Il suo meglio per dividere il file in più parti e caricare . Unire i pezzi sul lato server.