RewardedAd causes memory leak. How to disable RewardedAd when destroying the activity in Android?

1,323 views
Skip to first unread message

Pablo Alfonso

unread,
May 21, 2020, 9:12:08 AM5/21/20
to Google Mobile Ads SDK Developers

My Activity is still in the memory after running "finish()" and OnDestroy(). It is not garbage collected.

After days of analysis with Memory Profiler I have isolated the issue in the RewardedAd.

Basically, if I comment the entries in createAndLoadRewardedAd() method, where rewardedAd is initialized, the activity is properly destroyed:

private RewardedAd createAndLoadRewardedAd() {

    if (1==1) return null;  //IF THIS LINE IS COMMENTED, THERE WILL BE MEMORY LEAK!!!

    RewardedAd rewardedAd = new RewardedAd(this,
            getResources().getString(R.string.rewards_ad_unit_id));
    RewardedAdLoadCallback adLoadCallback = new RewardedAdLoadCallback() {
        @Override
        public void onRewardedAdLoaded() {
            // Ad successfully loaded.                
        }

        @Override
        public void onRewardedAdFailedToLoad(int errorCode) {
            // Ad failed to load.                
        }
    };
    rewardedAd.loadAd(new AdRequest.Builder().build(), adLoadCallback);
    return rewardedAd;
}

I have implemented rewardedAd as stated in the official documentation: https://developers.google.com/admob/android/rewarded-ads

Unfortunately, this document does not provide instructions to disable/destroy/nullify the related objects.

I'm setting rewardedAd to null in onDestroy, but this is not enough.

Mobile Ads SDK Forum Advisor Prod

unread,
May 21, 2020, 9:47:26 AM5/21/20
to google-adm...@googlegroups.com
Hi Pablo,

Thank you for bringing this documentation issue and leak issue in Android Rewarded Video to our attention. I found in our sample rewarded app - https://github.com/googleads/googleads-mobile-android-examples/blob/c9c358e67115ede18d29d9ac25b06d9bf082e0b8/java/admanager/NativeAdsExample/app/src/main/java/com/google/example/gms/nativeadsexample/MainActivity.java all the native ad destroy methods recommended by our team as of this time. I will request from my team that the implementation documentation be updated. If the documentation is changed you will see it here - https://developers.google.com/admob/android/rewarded-ads.

If after implementing all the destroy methods that are recommended in our sample you still see memory leaks then then could you send us a sample project based on our sample app with just enough of your own code to recreate the issue?

Kind regards,
Aryeh Baker
Mobile Ads SDK Team

ref:_00D1U1174p._5004Q1zqwQm:ref

Mobile Ads SDK Forum Advisor Prod

unread,
May 21, 2020, 10:25:41 AM5/21/20
to google-adm...@googlegroups.com
Hi Pablo,

Please disregard my mistake of discussing Native Ads when your concern was with Rewarded Ads. Could you send us a bare bones project based on our sample Rewarded app here - https://github.com/googleads/googleads-mobile-android-examples/releases/tag/5.7 (look for AdMob Rewarded) with just enough of your code to replicate the memory leak that you found? Please tell us the steps you took to create the memory leak.

Kind Regards,
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Pablo Alfonso

unread,
May 21, 2020, 10:26:03 PM5/21/20
to google-adm...@googlegroups.com
I have reproduced the issue with a simple project based on your "AdMob Rewarded Video Example".
I will update this forum with the details soon.
Regards,
-Pablo.


Pablo Alfonso

unread,
May 21, 2020, 10:26:40 PM5/21/20
to google-adm...@googlegroups.com
Based on the provided example, I moved the rewardedAd object and its methods from the MainActivity to a SecondActivity
so you can easily reproduce the issue by pressing the Back button from this SecondActivity.
In SecondActivity.java I added an onBackPressed() method with "finish();" execution.
In OnDestroy method, I'm just running this line:

if (rewardedAd != null) rewardedAd = null;


I'm also showing the message "onRewardedAdLoaded" on-screen whenever the ad is loaded:

Toast.makeText(SecondActivity.this, "onRewardedAdLoaded", Toast.LENGTH_SHORT).show();




The following are the steps to reproduce the issue and verify the Memory Leak:

1. From Android Studio, open the Profiler.
2. Launch the application.
3. Press "Second Activity" button.
4. Press Back button.
5. From the memory Profiler, you can press the trash can icon a few times to force garbage collection.
6. Then press "Dump Java Heap" icon.
7. When the Java Heap is generated, press the "Activity/Fragments Leaks" checkbox.
8. SecondActivity is shown in the app heap as seen on this screenshot: MemoryLeakInSecondActivityWithRewardedAd.jpg


In order to compare the results when running the same project without the RewardedAd, comment the "loadRewardedAd();" entry
from the OnCreate method in SecondActivity.java...


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Log.v(TAG,"Second Activity");
        setContentView(R.layout.second_activity);




    MobileAds.initialize(this, new OnInitializationCompleteListener() {
      @Override
      public void onInitializationComplete(InitializationStatus initializationStatus) {
      }
    });


    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    // COMMENT THIS LINE TO COMPARE THE RESULTS.
    // WHEN THIS LINE IS COMMENTED THERE IS NO MEMORY LEAK AFTER PRESSING BACK BUTTON
    //loadRewardedAd(); 
    // !!!!!!!!!!!!!!!!!!!!!!!!!!




Try to reproduce the issue again:

1. From Android Studio, open the Profiler.
2. Launch the application.
3. Press "Second Activity" button.
4. Press Back button.
5. From the memory Profiler, press the trash can icon a few times to force garbage collection.
6. Then press "Dump Java Heap" icon.
7. When the Java Heap is generated, press the "Activity/Fragments Leaks" checkbox.
8. No leaks are shown as seen on this screenshot: NoMemoryLeakWithoutRewardedAd.jpg




This is what I found:
If you wait a few seconds on SecondActivity before pressing Back button, you will see the "onRewardedAdLoaded" message on this same SecondActivity (as expected).
However, if you press the Back Button quickly "onRewardedAdLoaded" MESSAGE IS SHOWN ON MAINACTIVITY!! This clearly indicates that the RewardedAd is still active!
This is not supposed to happen If I find a way to disable or kill the ad object as part of the activity disposal.

Regards,
-Pablo.
Message has been deleted
Message has been deleted

Pablo Alfonso

unread,
May 21, 2020, 10:32:35 PM5/21/20
to Google Mobile Ads SDK Developers
1. Attached screenshot showing memory leak when using RewardedAd.
2. Attached screenshot showing NO memory leak when RewardedAd is NOT used.
MemoryLeakInSecondActivityWithRewardedAd.jpg
NoMemoryLeakWithoutRewardedAd.jpg
Message has been deleted
Message has been deleted

Pablo Alfonso

unread,
May 21, 2020, 10:38:22 PM5/21/20
to Google Mobile Ads SDK Developers
I'm getting error when trying to attach the project file (RewardedAdMemoryLeak.zip):

"There was an error posting the message to the group"

Is there any other way to upload or send this file to you? Via email?

Mobile Ads SDK Forum Advisor Prod

unread,
May 22, 2020, 1:42:25 AM5/22/20
to google-adm...@googlegroups.com

Hi Pablo,

 

You may send us your sample project via Google Drive or via any other filesharing service that you prefer. Don't forget to send the link via Reply privately to author.

 

Regards,

Ziv Yves Sanchez

Pablo Alfonso

unread,
May 22, 2020, 7:47:29 AM5/22/20
to Google Mobile Ads SDK Developers
I have sent the link (google drive) via "Reply privately to author".
Please confirm if you have received it.
Regards,
-Pablo.

Mobile Ads SDK Forum Advisor Prod

unread,
May 22, 2020, 8:35:07 AM5/22/20
to google-adm...@googlegroups.com
Hi Pablo,

Unfortunately we did not receive your project. Could you try then by sending to mobileads...@gmail.com?

Regards,
Aryeh Baker

Pablo Alfonso

unread,
May 22, 2020, 9:08:05 AM5/22/20
to google-adm...@googlegroups.com
I'm getting error "Blocked for security reasons" when trying to send it via emai. My file is in zip format.

I have shared the project to "mobileads...@gmail.com" in Google Drive.

Please let me know if you can download it now.

Regards,
-Pablo.

On Friday, May 22, 2020 at 8:35:07 AM UTC-4, mobileadssdkforumadvisor wrote:
Hi Pablo,

Unfortunately we did not receive your project. Could you try then by sending to mobileadstesting99@gmail.com?
Message has been deleted

Mobile Ads SDK Forum Advisor Prod

unread,
May 22, 2020, 11:40:39 AM5/22/20
to google-adm...@googlegroups.com
Hi Pablo,

Thank you for the full setup to test for a leak! I was able to follow your instructions easily. You have made an exemplary bug report and here are my findings:
  • When I load the second activity and then right away load the main activity then the toast from the second activity will show in the first activity and a heap dump will show the second activity even after some garbage collection. 
  • When I do the above but wait a minute and then garbage collect only the main activity shows in the heap dump
  • When the ad fully loads before I switch back to the main activity and I do a garbage collection and heap it's the same as above.
  • When I commented out ad loading there's no memory leak.
This is a temporal memory leak of an infrequent activity. If a user presses back from a rewarded ad to another activity and there is a delayed toast in the rewarded ad activity then that toast will show up in the main activity. It would be helpful for anyone reading this post to give us use cases where this issue causes trouble so that we can prioritize a fit solution. I will be consulting with my team and we will get back to you as soon as we have more useful information.

Kind regards,

Pablo Alfonso

unread,
May 22, 2020, 12:58:09 PM5/22/20
to google-adm...@googlegroups.com
Hi Aryeh, 

Thank you for your comments. I hope this case applies for the bug bounty reward program then :)


The following are my comments about the four scenarios that you described:


- "When I load the second activity and then right away load the main activity then the toast from the second activity will show
 in the first activity and a heap dump will show the second activity even after some garbage collection." 
TRUE!

- "When I do the above but wait a minute and then garbage collect only the main activity shows in the heap dump."
I cannot reproduce this scenario. I still see the "secondActivity" forever (after one minue and after five minutes).
Can you please double check? I'm testing with a real device here.


- "When the ad fully loads before I switch back to the main activity and I do a garbage collection and heap it's the same as above."

I cannot reproduce this scenario. I still see the "secondActivity" forever no matter where and when the ad is loaded.



- "When I commented out ad loading there's no memory leak."
TRUE!




"This is a temporal memory leak of an infrequent activity."
This does not appear to be a temporal memory leak in my case. The only way to free the memory is by restoring the app
so this seems to be a very critical Bug for me.
Also, this does not appear to be infrequent. Leaving an activity with an ad fully loaded is absolutely expected.

Suppose this simple case: If this activity is heavily working on bitmaps, and it is not possible to destroy it due to this Ad object, 
there will be an outofmemory crash sooner or later.

The best example I can provide is my app: 


This is a card game where users can play with different card games (created by same users or native).
In one of the activities ("View/Edit Decks") my app shows a list of card decks as seen in the attached screenshot.
Some of these decks are called "Gift Decks", so users have to watch a RewardedAd video to access to them.
If the user presses the back button on this activity I end up with a HUGE memory leak (as I cannot destroy the activity as a whole).
After using the app for a while an outofmemory will happen. This means lost revenue for me and for Google.
After finding this bug, if it is not solved, my only "workaround" is to remove all objects of the activity (bitmaps, arrays, hashmaps, etc) one by one
and live with the activity instance forever. This is extremely inefficient.

Please also note that finding this bug took me months of investigation as I always discarded the Google SDK as a potential cause.
These days I just started to look at the ads as the potential cause. 
I guess that if the activity where the rewardAd exists is not consuming memory (i.e. any regular activity where no bitmaps are used) the bug goes unnoticed for most of the apps (and developers)
but if a rewardedAd is used, there is no way to avoid this memory leak and there will be an outofmemory crash sooner or later.

Thanks!
-Pablo.
RealExample.png

Mobile Ads SDK Forum Advisor Prod

unread,
May 22, 2020, 1:38:40 PM5/22/20
to google-adm...@googlegroups.com
Hi Pablo,

Thank you for getting back to me with your experience and use case. I retested your sample app and 1 minute after I return to main activity after the toast appears while main activity is active there's no leak. A heap snapshot taken 10 seconds after return to main activity shows the 2nd activity. I downloaded your app and opened and closed many rewarded ads and didn't create a crash in my device. My device is a Xiaomi mi A2 Android version 10, and if your memory leak is temporal on my phone it isn't surprising I wasn't able to crash your app. I passed your comments along to my team. Could you forward to us the names of all device types and operating systems you know of that have crashed your app due to memory leak so that we can test on our end? Could. you delineate which ones you tested with and found that the leak doesn't go away?

Pablo Alfonso

unread,
May 22, 2020, 2:04:44 PM5/22/20
to google-adm...@googlegroups.com
Hi Aryeh, 

The reason why you cannot reproduce the outofmemory with my app now is because I recently released a new version with the workaround described before
(i.e. remove most of the most memory consuming objects in onBackPressed()).

I will gather the information about the outofmemory crashes in my app. 
I will need to check my crashlytics reports and filter by this specific activity.
It will take me a while as I removed them from the report. Probably, I will see more cases from other activities
using RewardedAd (I did not test them yet).


Anyways, as I can easily reproduce the issue with this example project, the following is the information
about my testing device (and Android Studio if it is relevant):


Testing Device:
Phone Name: LG G Stylo
Model Number: LGMS631
Hardware version: Rev.1.0
Android version: 6.0 (I know, it is old, not sure if this is relevant).
Kernel version: 3.10.49

Android Studio version: 3.6.3


Plese let me know if you need further information about these testings.
Maybe we are not reproducing the issue in the same way though is simple as we just need
to press a back button (regardless of the timing).

I will try to reproduce the issue with an emulator too.

I'm open to do a zoom session if needed to proceed with the investigation.


Regards,
-Pablo.

Mobile Ads SDK Forum Advisor Prod

unread,
May 22, 2020, 2:31:22 PM5/22/20
to google-adm...@googlegroups.com
Hi Pablo,

Thank you for getting back to me with your device information which I forwarded to the rest of my team, for the effort you put into clarifying this issue and for for your expressed intent to help with more information. Unfortunately I cannot make my self available to do a conference, but your presentation is clear enough to go forward on and I would be the first to nominate you as bug reporter of the year;)  We are looking forward to hearing as much as possible the devices that have this issue so that we would be capable of making a more comprehensive solution.

Pablo Alfonso

unread,
May 22, 2020, 8:04:22 PM5/22/20
to google-adm...@googlegroups.com
Hi Aryeh, 

I have tested the small project with more devices today:

1. Real device: LG K10
Model: LGMS428
Android Version: 7.0 (Nougat)
Kernel Version: 3.10.49

In this device the SecondActivity is still there forever (i.e. memory leak).
I'm attaching the screenshot of a heap dump in MainActivity after forcing Garbage Collection several times.


2. EMULATORs:  I have tested "7.0", "7.1.1", "8.1" and "10.0".

In ALL the emulators the behaviour is as you described:
    -  SecondActivity is destroyed after pressing back button and after a few seconds.
    -  The "onRewardedAdLoaded" message sometimes appears on MainActivity !
        Please note that this specific situation (i.e. Ad loaded in MainActivity after destroying the Secondactivity) might be considered a separate bug on its own: Even if this is not affecting the memory, this is affecting the matching rates for sure. Why would Google fully load an Ad that will never be shown (as the showAd methods will only exist in the destroyed activity)? How can we kill this task before leaving the activity?


Anyways, my priority is the memory leak now:
So at this point, it is not clear if the memory issue is reproduced in real devices with earlier Android versions only.
I hope your team has more resources (more real testing devices) and more expertise than me to test this thoroughly and confirm the criticality of this bug.
I recommend to test with 8.0 and 9.0 (real devices) too.


Thank you,
-Pablo.
MemoryLeakInNougat7.jpg

Mobile Ads SDK Forum Advisor Prod

unread,
May 26, 2020, 1:47:20 AM5/26/20
to google-adm...@googlegroups.com
Hi Pablo,

I work along with Aryeh. Thank you for the additional context. Let me relay this information to the team. I'll update you the soonest they provide their feedback.

Regards,
Teejay Pimentel

Zerrouk Hassan

unread,
May 31, 2020, 5:33:34 AM5/31/20
to Google Mobile Ads SDK Developers
Hi every one i'm facing thid problem when i load rewardVideo from another Activity and i press back button and i enter again 


E/MediaCodec: Codec reported err 0xffffec77, actionCode 0, while in state 3
D/SurfaceUtils: disconnecting from surface 0x65bfb808, reason disconnectFromSurface
E/MediaCodec: configure failed with err 0xffffec77, resetting...
I/ACodec:  [OMX.qcom.video.decoder.avc] Now uninitialized
I/ACodec:  [] Now kWhatShutdownCompleted event : 8600
I/MediaCodec: Codec shutdown complete
I/ACodec:  [] Now uninitialized
I/ACodec: [] onAllocateComponent
I/OMXClient: IOmx service obtained
I/ACodec: [OMX.qcom.video.decoder.avc] Now Loaded
E/ExoPlayerImplInternal: Renderer error.
    com.google.android.gms.ads.exoplayer3.c
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.x(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:16)
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.b(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:4)
        at com.google.android.gms.ads.exoplayer3.video.h.b(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:5)
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.a(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:6)
        at com.google.android.gms.ads.exoplayer3.n.handleMessage(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:122)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:214)
        at android.os.HandlerThread.run(HandlerThread.java:65)
     Caused by: com.google.android.gms.ads.exoplayer3.mediacodec.b: Decoder init failed: OMX.qcom.video.decoder.avc, Format(1, null, video/avc, -1, null, [1280, 720, -1.0], [-1, -1])
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.x(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:15)
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.b(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:4) 
        at com.google.android.gms.ads.exoplayer3.video.h.b(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:5) 
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.a(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:6) 
        at com.google.android.gms.ads.exoplayer3.n.handleMessage(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:122) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.os.HandlerThread.run(HandlerThread.java:65) 
     Caused by: android.media.MediaCodec$CodecException: Error 0xffffec77
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:1960)
        at android.media.MediaCodec.configure(MediaCodec.java:1889)
        at com.google.android.gms.ads.exoplayer3.video.h.a(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:49)
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.x(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:13)
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.b(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:4) 
        at com.google.android.gms.ads.exoplayer3.video.h.b(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:5) 
        at com.google.android.gms.ads.exoplayer3.mediacodec.c.a(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:6) 
        at com.google.android.gms.ads.exoplayer3.n.handleMessage(:com.google.android.gms.policy_ads_fdr_dynamite@21829057@21829057.311174395.311174395:122) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.os.HandlerThread.run(HandlerThread.java:65) 

i try to use if (rewardedAd != null) rewardedAd = null; 
but the problem still :/ any help please


On Thursday, 21 May 2020 14:12:08 UTC+1, Pablo Alfonso wrote:

My Activity is still in the memory after running "finish()" and OnDestroy(). It is not garbage collected.

After days of analysis with Memory Profiler I have isolated the issue in the RewardedAd.

Basically, if I comment the entries in createAndLoadRewardedAd() method, where rewardedAd is initialized, the activity is properly destroyed:

private RewardedAd createAndLoadRewardedAd() {

    if (1==1) return null;  //IF THIS LINE IS COMMENTED, THERE WILL BE MEMORY LEAK!!!

    RewardedAd rewardedAd = new RewardedAd(this,
            getResources().getString(R.string.rewards_ad_unit_id));
    RewardedAdLoadCallback adLoadCallback = new RewardedAdLoadCallback() {
        @Override
        public void onRewardedAdLoaded() {
            // Ad successfully loaded.                
        }

        @Override
        public void onRewardedAdFailedToLoad(int errorCode) {
            // Ad failed to load.                
        }
    };
    rewardedAd.loadAd(new AdRequest.Builder().build(), adLoadCallback);
    return rewardedAd;
}

I have implemented rewardedAd as stated in the official documentation: https://developers.google.com/admob/android/rewarded-ads

Unfortunately, this document does not provide instructions to disable/destroy/nullify the related objects.

I'm setting rewardedAd to null in onDestroy, but this is not enough.

Mobile Ads SDK Forum Advisor Prod

unread,
Jun 1, 2020, 1:35:17 AM6/1/20
to hassant...@gmail.com, google-adm...@googlegroups.com
Hi Zerrouk,

I could see that you opened a new thread with this issue. For better tracking of issue, I would recommend to continue the discussion in that thread instead.

p_al...@yahoo.com

unread,
Sep 17, 2020, 5:26:59 PM9/17/20
to Google Mobile Ads SDK Developers
Any solution?

Mobile Ads SDK Forum Advisor Prod

unread,
Sep 17, 2020, 8:16:03 PM9/17/20
to google-adm...@googlegroups.com
Hi there,

Thanks for following up this thread.

Our team is currently looking into this; however, allow me to make a follow up on this. We'll be updating this thread for any available feedback.

Regards,
Google Logo
Mark Kevin Albios
Mobile Ads SDK Team
 


ref:_00D1U1174p._5004Q1zqwQm:ref

Mobile Ads SDK Forum Advisor Prod

unread,
Sep 21, 2020, 3:53:18 AM9/21/20
to google-adm...@googlegroups.com

Hi Everyone,

Thanks for your patience on this.

Please see updates from our team below:

"We retain the reference to the activity while the ad is loading. If the load completes or times out then the reference is no longer held and can be cleaned up, therefore resulting in no leak. That's why the leak is temporary. If you're using a lot of memory and loading ads is causing you to get out of memory crashes, then you would need to try to reduce overall memory usage by not loading as many ads at once or by using queues (to manage bitmap handling for example). The SDK needs reference to the activity while the load is occurring in order to avoid unexpected behavior which would manifest as other bugs."

Regards,

Reply all
Reply to author
Forward
0 new messages