3

I have a test project which demonstrates a memory leak caused by Admob 4.1.1.

The basic scenario is I have two activities and I switch back and forth between the main and the sub activity several times. I then switch to DDMS and force a few GCs. Then dump the HPROF and look at the historgram filtered by com.test* to see how many instances of the main and sub activity there are. My screenshots of the histogram are attached:

A leak! leaks

I then commented out the ads in the xml and reran and there were no leaks:

No leak now no leak

I have found some relevant posts to Admob leaks such as here: Android AdMob causes memory leak?

Here is a list of things I have tried to resolve the issue:

  1. Wait some amount of time and then force gc
  2. Do not load the ad in oncreate but spawn a thread to wait then load it
  3. Tried a previous version of Admob (the one not written by Google)
  4. Called adView.destroy() in the onDestroy() activity's method
  5. The unbinding from this link

Obviously none of these things helped.

Here is the test project I wrote:

(Be sure to set your own publisher id when you run the test project)

download test leak android project

If it makes a difference I'm tesing on my SGS2 with Cyanogenmod ROM.

Does this happen for other people when they run this project?

Does anyone know the cause a fix or a workaround?

Thanks

Community
  • 1
  • 1
timothyjc
  • 2,188
  • 3
  • 29
  • 54
  • My *best* work-around atm is to use the unbinding which I mentioned in the post. This minimizes the footprint of the leaked activities so that you can have hundreds of them open without getting OOMs. Not exactly ideal :( – timothyjc Oct 08 '11 at 09:46
  • See my solution here: http://stackoverflow.com/questions/6148812/android-admob-causes-memory-leak/8364820#8364820 – TacB0sS Dec 03 '11 at 01:41
  • Im not sure if that helps but I created a bug on Android support site. Admob is currently held by Google so they should do something about it. I was pretty supprised that this bug wasn't there already. [ISSUE 59627](http://code.google.com/p/android/issues/detail?id=59627&thanks=59627&ts=1378046413) – Mark Sep 01 '13 at 14:43

3 Answers3

2

My app uses 80% of the allowed 16Mb and the AdView leaks at every orientation change (since android destroys and recreates the whole activity then). As a result I am out of memory after a dozen or so orientation changes giving me the dreaded:

10-08 10:14:47.178: ERROR/dalvikvm-heap(2876): 1440000-byte external allocation too large for this process.

10-08 10:14:47.178: ERROR/dalvikvm(2876): Out of memory: Heap Size=5191KB, Allocated=2877KB, Bitmap Size=18675KB

10-08 10:14:47.178: ERROR/GraphicsJNI(2876): VM won't let us allocate 1440000 bytes

or similar.

The increase in memory can easily be seen in eclipse by doing a debug run and opening Window > Open perspective > Other > DDMS, clicking the "update heap" icon and doing a Cause GC. The easiest way to check imho is the #Objects. If the orientation has changed from portrait to landscape and back, the number of Objects should be exactly the same (and without AdView it is).

I work around the memory leak by making the AdView static

private static AdView mAdView = null;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(mAdView == null)
    {
        mAdView = new AdView(this, AdSize.BANNER, ADMOB_PUBLISHER_ID);
    }
}

and not calling the destroy

@Override
public void onDestroy() {
    super.onDestroy();
    //mAdView.destroyDrawingCache();
    //mAdView.destroy();
    //mAdView = null;
}

At least this prevents memory leaks between every orientation change.

Also I set request to null after using it. Don't know if that helps.

    AdRequest request = new AdRequest();
    mAdView.loadAd(request);
    request = null;
Ghandi
  • 36
  • 1
  • Do you programmatically add the AdView to your layout then? I created a LinearLayout to hold the AdView and proceeded as you did and there were no more leaks, but the ads were not clickable either and it was a bit of a pain detatching the static AdView from the previous views before it could be reused. – timothyjc Oct 09 '11 at 19:27
  • I suddenly started seeing the out of memory messages after I updated to a new Eclipse (I know, that shouldn't matter). I was using an Admob library from 2010. I upgraded to Admob 4.3.1, which required me to change all my Android Admob code. Now, I do not see any errors. – Lucy Feb 29 '12 at 21:18
1

My solution

private void destroyWebView(ViewGroup viewGroup) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {
    if (viewGroup.getChildAt(i) instanceof WebView) {
        WebView view = (WebView) viewGroup.getChildAt(i);
        viewGroup.removeView(view);
        view.destroy();
        return;
    }
}
}

@Override
protected void onDestroy() {
mAdView.stopLoading();
destroyWebView(mAdView);
((ViewGroup) mAdView.getParent()).removeView(mAdView);
Bohdan
  • 11
  • 1
-1

Yes, I build it all up dynamically. I use removeAllViews to remove all views from my (LinearLayout) container. Then I use addView to put them all back again. The ad is clickable. Is there perhaps some transparent view in front of it in your case?

Darren
  • 68,902
  • 24
  • 138
  • 144
Ghandi
  • 1