2

I'm downloading a rather large file on the SD card of an Android device (~60MB). The download goes fine, but I need to pull this file in its entirety into memory. I know that's a huge chuck of memory for a smart phone, but I know my device has more than double that amount. Anyway, my actual problem is I get a OutOfMemoryError when reading the file into a byte array. Is there any way to increase the allocated memory for my application, or some way to "fake" reference the file yet keep the file in external storage without loading it into internal memory?

Jason Robinson
  • 31,005
  • 19
  • 77
  • 131
  • Can't you pre-allocate the buffer size(in the `InputStream`)? Maybe try that. 60MB is a lot for any app to have without garbage collecting. I would expect Android to lease that much data at any one point in the app anyways. You could also try separating the data into an array of byte arrays. – hwrdprkns Jun 30 '11 at 03:11
  • Your question isn't complete enough. What kind of data are you trying to handle? – Jeremy Edwards Jun 30 '11 at 06:24

2 Answers2

5

Each Virtual Machine instance in Android has what they called a VM Budget. This basically is the max amount of memory the entire app can occupy and nothing more. getRuntime().maxMemory() will give you the vm budget size for your current instance.

The budget can go anywhere from 16MB (G1) to 48MB (Moto Xoom) I think. Those numbers could be different as I'm trying to remember off the top of my head.

Usually for something like this you'd read the data in as an InputStream and process the data as you read it but don't retain the data itself.

If this is a Bitmap. You can use...

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; // Divides the width and height each by 4 when reading the data in.
Bitmap bitmap = BitmapFactory.decodeFile(String "filePath", options);
Bitmap bitmap = BitmapFactory.decodeStream(InputStream "fileStream", options);
Jeremy Edwards
  • 14,620
  • 17
  • 74
  • 99
  • Thanks, updated the comment. I'd be nice to have a chart of the memory classes over at http://developer.android.com/resources/dashboard/screens.html well really device-by-device specifications. – Jeremy Edwards Jun 30 '11 at 06:22
  • That's something I can't do, as it's a proprietary binary file (specialized for this application, though not originally conceived for Android) and the library I was given wants the entire file as a byte array...I know this is extremely ugly, but I wanted to see if there was anything I could do on my end before I go back to them and tell them this library won't work on Android. – Jason Robinson Jun 30 '11 at 14:20
  • That's quite unfortunate. You should really try to sort that out wiht the 3rd party vendor. A big problem is that you should play nice with other apps. Consuming too much memory puts significant strain on the system. – Jeremy Edwards Jun 30 '11 at 22:57
  • Fair enough. We're going to suggest they let us pass in an InputStream from the file on the SD card to save on memory. Thanks. – Jason Robinson Jul 01 '11 at 18:55
1

The simple answer is: You should really reconsider your current design. Could you explain why you would need to load 60mb of data into memory?

ChrisWue
  • 18,612
  • 4
  • 58
  • 83
Maurycy
  • 3,911
  • 8
  • 36
  • 44
  • this amount of data would make a database more than appealing, if it's possible – Snicolas Jun 30 '11 at 03:18
  • It's a proprietary binary file, and the library I was given to read this file wants the entire thing as a byte array...so I'm a bit limited in that regard. – Jason Robinson Jun 30 '11 at 14:17
  • Thats tough. There are other considerations. Maybe have a separate process / thread dedicated to the decoding maybe with a server/client relationship. Meaning have the file be processed on server then downloaded to client and streamed or viewed. This is just an example of a redesign that might be necessary. Good Luck. – Maurycy Jul 06 '11 at 04:08