I have upgraded the ads library to the following today:
implementation 'com.google.android.gms:play-services-ads:21.5.0'
I'm using Interstitial Ads only.
Now, I'm getting the following memory leak as detected by Leak Canary.
I'm destroying the activity along with all related ads objects, such as setting them to null, listeners to null, setFullScreenContentCallback(null), etc.
┬───
│ GC Root: Input or output parameters in native code
│
├─ android.os.MessageQueue instance
│ Leaking: NO (MessageQueue#mQuitting is false)
│ HandlerThread: "ExoPlayerImplInternal:Handler"
│ ↓ MessageQueue[0]
│ ~~~
├─ android.os.Message instance
│ Leaking: UNKNOWN
│ Retaining 2.5 MB in 605 objects
│ Message.what = 2
│ Message.when = 507477121 (661 ms after heap dump)
│ Message.obj = null
│ Message.callback = null
│ Message.target = instance @348531240 of android.os.Handler
│ ↓ Message.target
│ ~~~~~~
├─ android.os.Handler instance
│ Leaking: UNKNOWN
│ Retaining 2.5 MB in 604 objects
│ ↓ Handler.mCallback
│ ~~~~~~~~~
├─ com.google.android.gms.internal.ads.zzatb instance
│ Leaking: UNKNOWN
│ Retaining 2.5 MB in 603 objects
│ ↓ zzatb.zzm
│ ~~~
├─ com.google.android.gms.internal.ads.zzaup instance
│ Leaking: UNKNOWN
│ Retaining 22.1 kB in 81 objects
│ ↓ zzaup.zzb
│ ~~~
├─ com.google.android.gms.internal.ads.zzatz instance
│ Leaking: UNKNOWN
│ Retaining 16 B in 1 objects
│ ↓ zzatz.zzb
│ ~~~
├─ com.google.android.gms.internal.ads.zzclf instance
│ Leaking: UNKNOWN
│ Retaining 346 B in 10 objects
│ zzd instance of com.google.android.gms.internal.ads.zzcpc, wrapping
│ androidx.multidex.MultiDexApplication
│ ↓ zzclf.zzd
│ ~~~
├─ com.google.android.gms.internal.ads.zzcpc instance
│ Leaking: UNKNOWN
│ Retaining 24 B in 1 objects
│ zza instance of com.xxxxx.xxxxx.CreateCardsActivity with
│ mDestroyed = true
│ zzb instance of androidx.multidex.MultiDexApplication
│ zzc instance of com.xxxxx.xxxxx.CreateCardsActivity with
│ mDestroyed = true
│ mBase instance of androidx.multidex.MultiDexApplication
│ zzcpc wraps an Application context
│ ↓ zzcpc.zza
│ ~~~
╰→ com.xxxx.xxxxxx.CreateCardsActivity instance
Leaking: YES (ObjectWatcher was watching this because
xxxx.xxxxx.CreateCardsActivity received Activity#onDestroy() callback and
Activity#mDestroyed is true)
Retaining 8.4 kB in 204 objects
key = 433e4c0b-dd8e-4321-a496-8a5a5542d28e
watchDurationMillis = 428997
retainedDurationMillis = 423991
mApplication instance of androidx.multidex.MultiDexApplication
mBase instance of androidx.appcompat.view.ContextThemeWrapper
METADATA
Build.VERSION.SDK_INT: 28
Build.MANUFACTURER: BLU
LeakCanary version: 2.10
App process name: com.xxx.xxxx
Class count: 20438
Instance count: 386631
Primitive array count: 252937
Object array count: 46275
Thread count: 148
Heap total bytes: 39734117
Bitmap count: 52
Bitmap total bytes: 29096284
Large bitmap count: 0
Large bitmap total bytes: 0
Db 1: open /com.google.android.
datatransport.events
Db 2: closed google_app_measurement_local.db
Db 3: open androidx.work.workdb
Stats: LruCache[maxSize=3000,hits=182820,misses=342787,hitRate=34%]
RandomAccess[bytes=16217423,reads=342787,travel=94405937828,range=40656354,size=
56429010]
Analysis duration: 149315 ms
This is how I set the fullScreenContentCallback in OnCreate():
FullScreenContentCallback fullScreenContentCallback = new FullScreenContentCallback() {
@Override
public void onAdDismissedFullScreenContent() {
mAdManagerInterstitialAd.setFullScreenContentCallback(null);
mAdManagerInterstitialAd = null;
}
};
This is how I load the ad:
AdManagerAdRequest adRequest = new AdManagerAdRequest.Builder().build();
AdManagerInterstitialAd.load(this,getResources().getString(R.string.interstitial_ad_unit_id), adRequest,
new AdManagerInterstitialAdLoadCallback() {
@Override
public void onAdLoaded(@NonNull AdManagerInterstitialAd interstitialAd) {
mAdManagerInterstitialAd = interstitialAd;
mAdManagerInterstitialAd.setFullScreenContentCallback(fullScreenContentCallback);
}
@Override
public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
// Handle the error
mAdManagerInterstitialAd = null;
}
I also tried to load the ad using getApplicationContext() instead of "this" as suggested in other forums but it did not work.
Any ideas?
This is more likely a bug in play-services-ads.
My workaround: Move mAdManagerInterstitialAd from the activity to a singleton. Then invoke 'load' and 'show' from the activity making reference to the mAdManagerInterstitialAd stored in the singleton, using callbacks and listeners.