AVOCARROT warning..... DO NOT USE (if you have more than one activity with native ad)

So, I just spent the better part of a day trying to figure this out and debug a memory leak, while my app is crashing in the wild.

  1. I did try to contract Avocarrot. They did not reply. I don’t know what time they go home.
  2. I hope they fix this FAST, since I replaced all my ads with Native.

Here is the leak:

First, I am using the Mopub Adapter found here: https://github.com/Avocarrot/android-adapters/blob/master/avocarrotadapter/src/main/java/com/mopub/nativeads/AvocarrotNativeMopub.java

Thanks guys! I wish more companies would provide MoPub adapters!

So, lets dive into the code…

The MoPub adapter calls AvocarrotCustom like this:

mAvocarrotCustom = new AvocarrotCustom((Activity)context, appId, placement, "mopub");

Notice how they are specifically passing in the context as an Activity? Well, what are they doing with it ?

public AvocarrotCustom(Activity activity, String apiKey, String placementName, String mediationType)
  {
    super(activity, apiKey, placementName, mediationType);
  }

Looks like just passing it to the base class… which does the following:


  BaseController(Activity activity, String apiKey, String placementName, String mediationType)
  {
    this.avocarrot = new Avocarrot(activity);
    .. blah... snipped...
    if (activity != null) {
      initializationsWithContext(activity);
    }
  }
  
  void initializationsWithContext(Activity activity)
  {
    this.imageManager = new ImageManager(activity);
    this.weakActivity = new WeakReference(activity);
  }

AND… in a heinous piece of sinful code, they don’t actually use the weakReference to the Activity!

Ok, so moving on, what does Avocarrot(activity) do ? First, it does not even care about the Activity… you could be passing it the application context!


Avocarrot(Context context)  {
    ... other stuff snipped....
    if (context != null) {
      initContextRequired(context);
    }
  }
void initContextRequired(Context context)
  {
    if (this.deviceInfo == null) {
      this.deviceInfo = new DeviceInfo(context);
    }
    if (!AvocarrotSentry.isInitialized()) {
      try
      {
        AvocarrotSentry.init(context, .... blah blah blah..... 

Ok, so here we see the Activity has been cast to a Context and passed to AvocarrotSentry… which is a Singleton btw…


public static void init(Context context, String dsn)
  {
    getInstance().context = context;

Yep, that’s right… the fscker just stored the context!!! … and just like that, we leaked the Activity! All they needed to do was try context.getApplicationContext() and they could leak the Application instead.

So, you might not want to use Avocarrot until they fix this…

To recap:

  1. They force you to use an Activity for context
  2. They they cast away the Activity and create a singleton and store the context in that, thereby leaking the Activity
  3. Have a nice day! I know I did… not!

Hi @mind - If you have already deployed your app to Google Play, please visit your dashboard so that you can immediately turn off all ads and make sure that your users will not be affected by this until the issue is fully investigated.

If you are still in sandbox, we appreciate your time for reporting this in detail and we will help you resolve it the earliest. A new SDK version has been released recently which could have introduced some complications for your use case as described above.

We do respect all the level of effort you’ve put yesterday on this and glad you find the mopub adapter useful.

Good to hear that. Unfortunately I also have problems with Avocarrot SDK, but with normal sdk, not plugin. New SDK is just crashing sometimes (not initialized error). So I downgrade the SDK to one which does not use recyclerView and now it is ok.

There is also another problem if you click the interstitial while its loading it would simply dissappear

Hi guys - @mmmkkksss could you please let me know the SDK version that you are using now and doesn’t have the issue? We’ve added common troubleshooting help in the documentation for the recyclerView support, however, we need to eliminate the unitialized error you received.
@taimur97 - I’ve opened this up as a new issue. Could you please let me know your SDK version and also help us reproduce it? Does this occur everytime an interstitial is loading?

My sdk version 3.3.4 Yes I can help you reproduce it. It occurs everytime the interstitial loads.

@taimur97 thanks! I’ll follow up through the dashboard chat for some clarifications needed.

Hello @mind - quick follow up on the memory leak issue.

The bad actor as you correctly identified is Sentry, our SDK logger, which is used to catch errors in the wild and enable us to be proactive. We will be deprecating Sentry with the next SDK release which is normally scheduled for next Friday Sept 4th.

I will keep you posted. In the meantime, if you want me to immediately turn off all ads in your apps to avoid potential crashes let me know.

How was Avocarrot working for your apps now guys?