安卓的OutOfMemoryError而上传视频 - 如何以最佳方式块? [英] Android: OutOfMemoryError while uploading video - how best to chunk?

查看:95
本文介绍了安卓的OutOfMemoryError而上传视频 - 如何以最佳方式块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我这里描述了同样的问题,但我会提供更多的一些细节。虽然试图上传Android的一个视频,我读入内存中,如果视频是很大,我得到一个OutOfMemoryError。

I have the same problem as described here, but I will supply a few more details. While trying to upload a video in Android, I'm reading it into memory, and if the video is large I get an OutOfMemoryError.

下面是我的code:

// 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(缓冲,0,len个)行):

And here's the traceback (the error is thrown on the byteBuffer.write(buffer, 0, len) line):

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

我想这作为@DroidIn建议,我需要上传的块。但是,(新手问题警报),这是否意味着我应该做多的PostMethod请求,和胶水文件一起在服务器端?或者,我可以加载的字节流入内存块,并且粘在一起,在Android code?

I guess that as @DroidIn suggests, I need to upload it in chunks. But (newbie question alert) does that mean that I should make multiple PostMethod requests, and glue the file together at the server end? Or can I load the bytestream into memory in chunks, and glue it together in the Android code?

如果任何人都可以给我一个线索,最好的方法,我将非常感激。

If anyone could give me a clue as to the best approach, I would be very grateful.

推荐答案

吉姆Blackler是绝对正确的。你不能在内存中完成视频中的byte []。所以,你应该阅读的文件不为byte [],而是直接到HttpUrlConnectio.getOutputStream()。

Jim Blackler is absolutely correct. You can't have complete video in memory in byte[]. So you should read file not to byte[] but directly to HttpUrlConnectio.getOutputStream().

但是,即使你仍然得到内存不足,因为HttpURLConnection的缓存在内存中的所有输出数据并将其发送到网络,只有当你完成写作。

But even after that you'll still get OutOfMemory because HttpUrlConnection caches all output data in memory and sends it to network only when you're complete writing.

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

To override this behaviour you can use HttpUrlConnection.setChunkedStreamingMode() or HttpUrlConnection.setFixedLengthStreamingMode(). If your server accepts stream chunks you can use setChunkedStreamingMode(). Otherwise you'll have to use setFixedLengthStreamingMode. To use setFixedLengthStreamingMode you'll need to know exact content length before starting streaming data, so it's a little bit tricky.

没有在这一点上更多的内存溢出。

No more OutOfMemory at this point.

如果你有你的视频文件,你可以选择另一种方式,更简单。使用的HttpClient和FileBody像<一个href="http://stackoverflow.com/questions/3038409/how-to-send-http-post-request-and-recieve-response/3038747#3038747">http://stackoverflow.com/questions/3038409/how-to-send-http-post-request-and-recieve-response/3038747#3038747.我觉得他们实现上面所有的方法,你就不必担心。

If you have your video in file you can choose another approach, much more simple. Use HttpClient and FileBody like that http://stackoverflow.com/questions/3038409/how-to-send-http-post-request-and-recieve-response/3038747#3038747. I think they implement all the methods above and you'll not have to worry about that.

这篇关于安卓的OutOfMemoryError而上传视频 - 如何以最佳方式块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆