14

My application has a lot of images and sometimes it crashes due to low memory. I wrote this function that I found on the developer site.

public void onLowMemory(){

}

But the problem is that this function never gets called during those low memory circumstances. What should I do to make this function to be called. I need to alert users when there is low memory on their device.

Abu Yousuf
  • 4,421
  • 2
  • 23
  • 39
James
  • 13,095
  • 26
  • 65
  • 92
  • "My application has a lot of images and sometimes it crashes due to low memory."- what means? Due to lots of Images Out Of memory or You want to know the storage devices memory? Both have a different scenario. :-) – user370305 Oct 11 '11 at 05:42

7 Answers7

12

onLowMemory() is not a big help because it gets called only at times where the overall system is running out of memory and not in cases where your app is running out of its available heap space.

So my answer is that you should not depend on onLowMemory() being invoked. And IMHO there is no callback method for your problem.

You can simply poll the available heap space and check whether you are running out of memory or not.

Runtime.getRuntime().maxMemory();
Runtime.getRuntime().totalMemory();
Runtime.getRuntime().freeMemory();
Zsolt Safrany
  • 11,950
  • 5
  • 48
  • 57
2

Along with onLowMemory() and onTrimMemory(), which monitor system memory, here's a way to monitor app memory. It uses Zsolt Safrany's answer at it's core.

private final float CHECK_MEMORY_FREQ_SECONDS = 3.0f;
private final float LOW_MEMORY_THRESHOLD_PERCENT = 5.0f; // Available %
private Handler memoryHandler_;

public void onCreate( Bundle savedInstanceState ) {

// Do Stuff...

 // Start Monitoring App Memory Availablity
    memoryHandler_ = new Handler();
    checkAppMemory();
}

public void checkAppMemory(){
    // Get app memory info
    long available = Runtime.getRuntime().maxMemory();
    long used = Runtime.getRuntime().totalMemory();

    // Check for & and handle low memory state
    float percentAvailable = 100f * (1f - ((float) used / available ));
    if( percentAvailable <= LOW_MEMORY_THRESHOLD_PERCENT )
        handleLowMemory();

    // Repeat after a delay
    memoryHandler_.postDelayed( new Runnable(){ public void run() {
        checkAppMemory();
    }}, (int)(CHECK_MEMORY_FREQ_SECONDS * 1000) );
}

public void handleLowMemory(){ 
    // Free Memory Here
}
Murtaza Khursheed Hussain
  • 14,714
  • 7
  • 52
  • 78
BuvinJ
  • 7,867
  • 3
  • 61
  • 78
  • Please, please don't do this!!! You might detect when you are running in "low" memory but you will kill the battery on the device since the CPU is constantly doing something (each 3s), you will prevent the device to go on DOZE mode for example – JavierSP1209 Jun 05 '18 at 12:35
  • So, never use ANY background polling mechanism on a mobile device? I don't think you are correct here. I'm pretty certain the app will still sleep. That was a spec I ran through my QA department when this code was written. Also, when you send the app to the background, this will not continue to run I don't believe. So, that negates the concern to a significant degree. – BuvinJ Jun 05 '18 at 13:20
  • Yes, actually you should avoid any polling mechanism and be more careful about leaking memory, you will not only drain battery but this could lead to leaking the Activity you are using it (reference inside `Runnable`). Regarding the app going to sleep, I think the problem is the hole device, but you can use the Profilers (CPU, Memory and Battery) to verify it, these are tools for developers to avoid this kind of problems. For a bit more information: https://www.youtube.com/watch?v=9i1_PnPpd3g. if you really wanna do this constantly, you can use `JobScheduler` or now a days `WorkManager` – JavierSP1209 Jun 05 '18 at 13:36
  • Thanks for the tips. I will more deeply investigate these concerns at some point. Note that, often one must use backwards compatible methods, so even if new classes and features become available, they may not be entirely applicable. – BuvinJ Jun 05 '18 at 15:16
1

Check Memory Analysis for Android Applications .

Arun Badole
  • 10,339
  • 19
  • 65
  • 93
0

As explained at android developers is hard to determine how much memory we have available for our app since: The exact heap size limit varies between devices based on how much RAM the device has available overall. So is a better approach to ask if we are running in a lowMemory environment using ActivityManager.MemoryInfo before doing a memory heavy operation like downloading an image or trying to load an image into memory, by doing this you will prevent OutOfMemoryExceptions

public void doSomethingMemoryIntensive() {

    // Before doing something that requires a lot of memory,
    // check to see whether the device is in a low memory state.
    ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();

    if (!memoryInfo.lowMemory) {
       // Do memory intensive work ...
    }
}
// Get a MemoryInfo object for the device's current memory status.
private ActivityManager.MemoryInfo getAvailableMemory() {
    ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);
    return memoryInfo;
}
JavierSP1209
  • 846
  • 6
  • 17
0

My application has a lot of images and sometimes it crashes due to low memory

That part is not clear, if your application is downloading any image from internet or end user picking image from gallery and adding it? In this case

  • you can warn the user that in order to add new images they must move back some already picked images
  • Or better you can remove the image from memory yourself using any algorithm(how about least recently used/viewed?)

    Another case is your application itself is using too much memory because of unneeded references and leaks..This case you never warn the user that there is no more memory..It is simply your responsibility to effectively use memory...This case normally arises mainly when

  • You are leaking a view/layout which are using many images, in this case you must find out the leak and resolve it..If you are using eclipse read about MAT
  • Rarely when the images are too big in size..This is a designers error..You can get good look and feel with images in the size of few kilo bytes...

In any case, it is unwise to alert user of low memory..A programmer should always program thinking you can make the app better by using less memory..

This thread will be very useful to know about your memory footprint inforamation..

And about usage of MAT tool...

Community
  • 1
  • 1
Krishnabhadra
  • 33,632
  • 30
  • 110
  • 164
-1

From API level 14, there's method called onTrimMemory(int) that fit your need.

Here's the doc:

http://developer.android.com/reference/android/content/ComponentCallbacks2.html

You're able to be notified when the system is about to recollect memory and also how critical the current situation is.

sbhhbs
  • 565
  • 3
  • 14
  • 1
    `onTrimMemory` has nothing to do with available heap space - it just takes overall (that is device wide) free memory into account and how long ago the app has been in foreground. – ubuntudroid Jan 09 '15 at 11:44
-2

Here is an example of how I'm using onLowMemory, implemented in MyApplication To clean things up, I do flush memory caches (which is used mainly for images), and google tracker;

@Override
    public void onLowMemory() {
        super.onLowMemory();
        Log.w(TAG, "onLowMemory() -> clearImageCacheFu!!!");
        clearImageCacheFu();

        dispatchGoogleTracker();
        stopGoogleTracker();
    }

This may give you an idea to adapt as per your need. hope this helps.

beerstorm
  • 7,882
  • 3
  • 28
  • 41
  • But for me this function never gets called. I am not using the @Override notation. IS that the reason. – James Oct 12 '11 at 15:50