Java Question Admob Interstitial Library Memory Leak

Jack Cole

Active Member
Licensed User
My wrapper for Admob interstitials has a memory leak. This occurs when you change orientations or load a new activity (that loads an interstitial) and close the activity. Part of the notion is that the library is holding a pointer to the activity, which prevents the activity and interstitial from being garbage collected. Any ideas for fixing this would be appreciated.

There is a post of stackoverflow.com that suggests the following:

interstitial =newInterstitialAd(this);

to

interstitial =newInterstitialAd(getApplicationContext());
Here is my code for the wrapper.

B4X:
package mobi.mindware.admob.interstitial;

import android.app.Activity;
import android.util.Log;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import com.google.android.gms.ads.*;
import android.os.Bundle;
import com.google.android.gms.ads.AdListener;

@BA.ActivityObject
@BA.ShortName("mwAdmobInterstitial")
@BA.Version(2.0F)
@BA.Author("Jack Cole")
@DependsOn(values={"google-play-services"})
@Permissions(values={"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE","android.permission.ACCESS_WIFI_STATE", "android.permission.READ_PHONE_STATE"})
@Events(values={"AdDismissed","AdFailedToLoad (ErrorMessage as String)","AdLoaded","AdClosed","Destroy"})
public class AdmobInterstitialsAds extends Activity
{
  public BA bA;
  private String eventName;
  private InterstitialAd interstitialAds;
  public Boolean isAdLoaded;
  public int Status;
  public static final int Status_Initialized = 0;
  public static final int Status_LoadingAd = 1;
  public static final int Status_AdReadyToShow = 2;
  public static final int Status_ShowingAd = 3;
  public static final int Status_NoAdAvailable = 4;
  public static final int Status_Dismissed = 5;
  public boolean isInitialized = false;

  public void Initialize(BA ba, String EventName, String AppId)
  {
      //Log.i("B4A", "1 - start initialize");
      this.isAdLoaded = Boolean.valueOf(false);

    this.bA = ba;

    this.eventName = EventName.toLowerCase(BA.cul);
    //
    this.interstitialAds = new InterstitialAd(ba.applicationContext);
    //this.interstitialAds = new InterstitialAd(Context.getApplicationContext());
    this.interstitialAds.setAdUnitId(AppId);
    //Log.i("B4A", "1 - before ad listener defined");
    this.interstitialAds.setAdListener(new AdListener() {
        @Override
        public void onAdLoaded() {
            //Log.i("B4A", "ON ad RECEIVED ");
            Status = 2;
            isAdLoaded = Boolean.valueOf(true);
            if (bA.subExists(eventName + "_adloaded"))
              bA.raiseEvent(this, eventName + "_adloaded", new Object[0]);
        }

        @Override
        public void onAdFailedToLoad(int errorCode) {
            Status = 4;
            //Log.i("B4A", "ON FAILED TO RECEIVE " + errorCode);
           
            if (bA.subExists(eventName + "_adfailedtoload"))
              bA.raiseEvent(this, eventName + "_adfailedtoload", new Object[] { getErrorReason(errorCode) });
        }

        @Override
        public void onAdClosed() {
            Status = 5;
           
            if (bA.subExists(eventName + "_adclosed"))
                bA.raiseEventFromDifferentThread(this, null, 0, eventName + "_adclosed", false, null);
        }
        @Override
        public void onAdLeftApplication() {
           
        } 
      

    });

    //Log.i("B4A", "1 - initialize end");
    this.isInitialized = true;
    this.Status = 0;
  }
 

  public void Destroy(BA ba){
      this.interstitialAds.setAdListener(null);
      this.interstitialAds=null;
  }
 
 
  public void LoadAd(BA ba) {
    this.interstitialAds.loadAd(new AdRequest.Builder().build());
    this.Status = 1;
  }

  public void Show(BA ba) {
    if (this.interstitialAds.isLoaded()) {
      this.interstitialAds.show();
      this.Status = 3;
    }
  }

  /** Gets a string error reason from an error code. */
  private String getErrorReason(int errorCode) {
    String errorReason = "";
    switch(errorCode) {
      case AdRequest.ERROR_CODE_INTERNAL_ERROR:
        errorReason = "Internal error";
        break;
      case AdRequest.ERROR_CODE_INVALID_REQUEST:
        errorReason = "Invalid request";
        break;
      case AdRequest.ERROR_CODE_NETWORK_ERROR:
        errorReason = "Network Error";
        break;
      case AdRequest.ERROR_CODE_NO_FILL:
        errorReason = "No fill";
        break;
    }
    return errorReason;
  }
}
 

Jack Cole

Active Member
Licensed User
That seemed to help some, but it's still losing about 500KB each time orientation is changed. Maybe that's the best that can be hoped for.
 
Top