Android Question Out of memory crash - how to check memory available

RJB

Active Member
Licensed User
Longtime User
Hi,
I am trying to load a lot of images - with the inevitable result that the app crashes due to 'out of memory'.
try/ catch does not catch the error, the app just crashes.
Is there any way to check the memory available so that I can take action to avoid the crash?
OS.setLowMemory, OS.AvailableExternalMemorySize and OS.AvailableInternalMemorySize do not help.
I'm assuming that the 'out of memory' refers to RAM(DDR) memory. Can I check now much of that is available/ free somehow?
Initializesample doesn't help. If I use it I get:

.........

62: IMAG0069.JPG
Downsampling image due to lack of memory: 2
Downsampling image due to lack of memory: 4
Downsampling image due to lack of memory: 8
Downsampling image due to lack of memory: 16
63: IMAG0070.JPG
Downsampling image due to lack of memory: 2
Downsampling image due to lack of memory: 4
Downsampling image due to lack of memory: 8
Downsampling image due to lack of memory: 16
Downsampling image due to lack of memory: 32
java.lang.RuntimeException: Error loading bitmap (OutOfMemoryError)

........

in debug mode

Thanks
 

DonManfred

Expert
Licensed User
Longtime User
How big (dimension, not size of jpgfile) are your images? How are you loading the images? Why you need "a lot of them" at once?
 
Upvote 0

RJB

Active Member
Licensed User
Longtime User
How big (dimension, not size of jpgfile) are your images? How are you loading the images? Why you need "a lot of them" at once?
Hi,
The images can be anything up to full HD i.e. 1920 x 1080.
I am loading the image by bitmap.initialize to a) get their dimensions and b) resize to the output size
I then use canvas.drawbitmap to resize.

B4X:
Dim Obj1 As Reflector
Obj1.Target=BMIn
Obj1.RunMethod("recycle")
doesn't help here

I am trying to keep them in memory to avoid processing/ delay at the point of displaying them.I think the impact on the display would be too high if I loaded them at that time (but I will experiment now that you have prompted me!)
 
Upvote 0

RJB

Active Member
Licensed User
Longtime User
You should use LoadBitmapSample to load the images (with the minimum size).
I had tried that but it still crashed as shown above 'downsizing image due ........'.
Presumably the code that produces those messages is checking what memory is available and hence trying to reduce the image size as necessary? Is it possible to use the same method? If so how?? If not then could it throw an error rather than just crashing the app?
Thanks
 
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime User
What you're looking for is heap size statistics:
B4X:
Dim r as Reflector
r.Target = r.RunStaticMethod("java.lang.Runtime", "getRuntime", Null, Null)
Log("Free Memory = " & (r.RunMethod("freeMemory")/(1024*1024)) & " MB")
Log("Max Memory = " & (r.RunMethod("maxMemory")/(1024*1024)) & " MB")

If you need to, you can add the following to the Manifest Editor to request a larger heap than the device's default heap size (default heap size and the size of the largeHeap will vary from device to device):
B4X:
SetApplicationAttribute(android:largeHeap,"true")
 
Upvote 0

RJB

Active Member
Licensed User
Longtime User
Thanks Roycefer that's really helped. The change to the manifest increased the 'max memory' from 64Mb to 384Mb and hence stopped the app crashing. As the device has 2Gb of RAM I don't think it will cause any other problems!
The 'Free Memory' figure seems a little strange though! It seems to be too small and to have too many decimal places so I'm wondering if it's actually showing the total free memory on the device and should be: r.RunMethod("maxMemory")/1024) & " Gb" ?? It's a shame because I'd still like to monitor the available memory (from the 384Mb) to that I can avoid potential crashes.
I had spent many hours searching and trying things when one simple change did the job!!!
Thanks again
 
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime User
java.lang.Runtime.getRuntime.maxMemory() should be returning its result in bytes. Same for freeMemory. Keep in mind that maxMemory is the size of the Dalvik (or ART) heap for the calling process, NOT the device's physical total RAM. Same with freeMemory.
 
Upvote 0

RJB

Active Member
Licensed User
Longtime User
java.lang.Runtime.getRuntime.maxMemory() should be returning its result in bytes. Same for freeMemory. Keep in mind that maxMemory is the size of the Dalvik (or ART) heap for the calling process, NOT the device's physical total RAM. Same with freeMemory.
That's what I thought but running 'Log("Free Memory = " & (r.RunMethod("freeMemory")/(1024*1024)) & " MB")' gives 'Free Memory = 0.1416187286376953 MB' or running 'Log("Free Memory = " & (r.RunMethod("freeMemory")) & " B")' gives 'Free Memory = 143826 B', neither of which seem to be particularly helpful!

I looked up the Runtime Class Summary and found 'totalMemory'.
If I run 'Log("available Memory = " & ((r.RunMethod("maxMemory") - r.RunMethod("totalMemory"))/(1024*1024)) & " MB") it gives me exactly what I need, i.e. I get 'out of memory' when it reaches 0MB.

Thanks for your help in getting there:)
 
Upvote 0
Top