Android : OutOfMemoryError при загрузке видео - как лучше кусок ?

? AP257 @ | Original: StackOverFlow

У меня такая же проблема http://stackoverflow.com/questions/1686446/upload-videos-in-android, но я буду поставлятьнесколько деталей . При попытке загрузить видео в Android, я читаю его в память, и есливидео большой я получаю OutOfMemoryError .

Вот мой код :

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

И воттрассировки (ошибка возникает на линии 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

Я думаю, что http://stackoverflow.com/questions/1686446/upload-videos-in-android, мне нужно, чтобы загрузить его на куски . Но ( новичок оповещения вопрос) это означает, что я должен сделать несколько запросов PostMethod, и приклейте файл вместе на стороне сервера ? Или я могу загрузить bytestream в памяти в куски, и склейте ее в Android код?

Если кто-то может дать мне ключ к тому, лучший подход, я был бы очень благодарен.

Top 5 ответ

1Jim Blackler @

Вам не нужно, чтобы получить весь файл в память, а затем загрузить его на одном дыхании. Позвоните connection.getOutputStream () и записи () байты в куски.

2Fedor @

Джим Blackler совершенно правильно. Вы не можете иметь полное видео в памяти байт []. Таким образом, вы должны прочитать файл не байт [], а непосредственно HttpUrlConnectio.getOutputStream ().

Но даже после этого вы все равно получите OutOfMemory, потому что HttpURLConnection кэширует все выходные данные в памяти и отправляет его в сеть только тогда, когда вы полностью писать.

Чтобы изменить это поведение можно использовать HttpUrlConnection.setChunkedStreamingMode () или HttpUrlConnection.setFixedLengthStreamingMode (). Если ваш сервер принимает поток куски можно использовать setChunkedStreamingMode (). В противном случае вы должны будете использовать setFixedLengthStreamingMode . Чтобы использовать setFixedLengthStreamingMode вы должны знать точную длину контента, прежде чем начать потоковые данные, так что этонемного сложнее.

Нет больше OutOfMemory в этой точке.

Если у вас есть видео в файл, который вы можете выбрать другой подход, гораздо более простой. Используйте HttpClient и FileBody так http://stackoverflow.com/questions/3038409/how-to-send-http-post-request-and-recieve-response/3038747#3038747, Я думаю, что они реализовывать все методы выше, и вы не будете иметь, чтобы беспокоиться об этом.

3Anthony @

Простозаписочку :

SetChunkedStreamingMode и setFixedeLengthStreamingMode не работают в Android 2.1, они работают совершенно в 2,0 и 2,2

4Rags @

Его лучше разбить файл на части и загружать . Слияние части в стороне сервера.