Android:上传视频时OutOfMemoryError - 如何最好的块?

时间:2010-04-08 11:10:07

标签: android

我有同样的问题as described here,但我会提供更多细节。在尝试在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

我想as @DroidIn suggests,我需要将其上传到块中。但是(新手问题警报)这是否意味着我应该发出多个PostMethod请求,并将文件粘合在服务器端?或者我可以将字节流加载到内存中,并将其粘贴在Android代码中吗?

如果有人能给我一个最佳方法的线索,我将非常感激。

4 个答案:

答案 0 :(得分:11)

吉姆·布莱克勒绝对正确。你不能在byte []中拥有内存中的完整视频。所以你应该把文件读取到byte []但是直接读取到HttpUrlConnectio.getOutputStream()。

但即使在那之后你仍然会得到OutOfMemory,因为HttpUrlConnection将所有输出数据缓存在内存中,并且只有在你完成写入时才将它发送到网络。

要覆盖此行为,您可以使用HttpUrlConnection.setChunkedStreamingMode()或HttpUrlConnection.setFixedLengthStreamingMode()。如果您的服务器接受流块,则可以使用setChunkedStreamingMode()。否则你将不得不使用setFixedLengthStreamingMode。要使用setFixedLengthStreamingMode,您需要在开始流数据之前知道确切的内容长度,因此这有点棘手。

此时不再有OutOfMemory。

如果您的视频存档,您可以选择其他方法,更简单。像How to send HTTP POST request and receive response?一样使用HttpClient和FileBody。我认为他们实施了上述所有方法,您不必担心这一点。

答案 1 :(得分:3)

您不需要将整个文件存储在内存中,然后一次上传。调用connection.getOutputStream()和write()块中的字节。

答案 2 :(得分:2)

请注意:

setChunkedStreamingMode和setFixedeLengthStreamingMode在android 2.1中不起作用,它们在2.0和2.2中完美运行

答案 3 :(得分:0)

最好将文件拆分为多个部分并上传。合并服务器端的部件。