1

Background

I'm trying to implement support for native ads from Admob.

The problem

I've noticed this requirement:

Ensure that all UnifiedNativeAd references are destroyed in your activity's onDestroy() method.

In your onUnifiedNativeAdLoaded callback, make sure to destroy any existing native ads that will be dereferenced.

However, I want to preload ads even before reaching the Activity, and if possible to re-use an ad when the Activity is recreated via configuration change (or at least on orientation change). Maybe even re-use the ad in multiple places, to reduce time of re-loading.

What I've found

I couldn't find explanation about this, except that it's ok to preload:

https://developers.google.com/admob/android/native/start?hl=en-US#when_to_request_ads

It also says that we shouldn't use ads that were preloaded and weren't used for an hour:

Any ad objects that have been held for longer than an hour without being displayed should be discarded and replaced with new ads from a new request.

As for the requirement to destroy the ad when there are no references to it, I've put a wrapper of the ad into a cached reference, and if I don't need it anymore I remove it from the cache. The wrapper should get rid of the ad using finalize, as such:

    class UnifiedNativeAdWrapper(private val ad: UnifiedNativeAd) {


        @UiThread
        fun getAd(): UnifiedNativeAd? {
            if (isDestroyed)
                return null
            return ad
        }

        @Suppress("MemberVisibilityCanBePrivate")
        var isDestroyed = false
            private set

        @Suppress("unused", "ProtectedInFinal")
        protected fun finalize() = destroy()

        @UiThread
        fun destroy() {
            if (isDestroyed)
                return
            isDestroyed = true
            ad.destroy()
        }
    }

The questions

  1. Is it ok to avoid destroying so quickly, on every time the Activity is destroyed? Maybe to destroy the ad only when it doesn't change configuration?

  2. Is it ok to have the wrapper I've made?

  3. Since it says that I should also avoid using ads that weren't used for an hour since being loaded, what happens to UnifiedNativeAdView that used an UnifiedNativeAd, once I call destroy on the UnifiedNativeAd ? Is it ok to call destroy on the old one that was used, while loading a new one? I want to avoid removal of the View while loading a new one...

  4. Since it says there could be multiple references to the ad, can the same instance of UnifiedNativeAd be used in multiple places (different Activities) ?

android developer
  • 114,585
  • 152
  • 739
  • 1,270

1 Answers1

1

From my knowledge I am going to try to answer your questions extensively.

  1. Destroying an ad from UnifiedNativeAdView or UnifiedNativeAd implicitly means you won't be able to create other UnifiedNativeAdView objects anymore using that ad, and, if you destroy the original UnifiedNativeAd object, the UnifiedNativeAdView that uses the assets of this UnifiedNativeAd may throw an exception, freeze etc... The behavior of that is mostly unknown, depending on the ad network you are using.

As long as you are removing the UnifiedNativeAdView itself from its parent, there should be no memory leaks occur, and you should be able to use the loaded native ad instance to create another view. The other approach could be calling UnifiedNativeAdView.removeAllViews() and then removing the view itself from its parent, but this might internally destroy the UnifiedNativeAd, and that's something I don't know, you need to test it for yourself.

  1. This depends, ensuring not calling destroy() on either of the classes might be up to you, but in the future, they might add a destroy() call on the UnifiedNativeAdView object itself (for instance, the view's onDetachedFromWindow method). Since there isn't a function to see if the ad is destroyed with a method like isDestroyed(), you should always try to create the views under try-catch, there is no other method I'm afraid. But, as long as that approach is not used from the SDK itself, it should be fine.

  2. You can use a Stack<UnifiedNativeAd> or something to put the loaded ads on, and, while creating the UnifiedNativeAdView object, you can call Stack.pop() so you know you already used the ad or the object doesn't exist anymore. But, you cannot use the same UnifiedNativeAdView to replace the native ad you are showing, you have to create a new one. This also means you can load multiple native ads and store them, basically.

Also you shouldn't worry about destroying the UnifiedNativeAd object itself after calling destroy from UnifiedNativeAdView since it internally destroys the native ad object anyway.

  1. Unless there is an internal reference to the context you loaded the ad is held in the UnifiedNativeAd object, you should be able to use the same ad by inflating different UnifiedNativeAdView objects to use the ad on different activities, as long as you ensure the ads are not destroyed. However, I don't recommend this approach since showing the same ad twice might break a policy or something.

This is all I know, hopefully it helps!

Furkan Yurdakul
  • 2,801
  • 1
  • 15
  • 37
  • 1. Did you test it? It should work even for native ads that have video? What happens if I re-use one that has a video, that played a bit, upon orientation change of the current Activity? Which approach do you use? 2. If they add it, it won't allow me to re-use for what you wrote on #1, no? 3. So I have to re-inflate each time I use a new ad? – android developer Aug 10 '20 at 10:43
  • 1
    @androiddeveloper 1. Yes, as long as you don't destroy the UnifiedNativeAd or UnifiedNativeAdView, the orientation change or activity recreation just pauses the video, then after activity gets recreated, you can use the same video in other UnifiedNativeAdView object. 2. That's basically the gist of it, yes. Currently you can use it, though. 3. Yes. – Furkan Yurdakul Aug 10 '20 at 11:21
  • 1. Do you do it on your app/s ? Meaning you avoid destroying the ad upon orientation change? – android developer Aug 11 '20 at 06:45
  • 1
    @androiddeveloper 1. Yes, I've done it multiple times on my apps, and still doing it. And, that does mean I avoid destroying it on orientation change, and only destroy it when user exits the app or leaves the screen. – Furkan Yurdakul Aug 11 '20 at 06:52
  • So you never had an issue with it? Even if it has video content in it? All you do is detach the view from its parent instead? If you don't do it, what happens? – android developer Aug 11 '20 at 08:27
  • 1
    I haven't really tried not removing the view, but an orientation change means the view gets removed anyway since activity gets recreated, unless you explicitly specify a `configChanges` attribute in manifest. I don't think it matters in your case, as long as you preserve the UnifiedNativeAd object and not destroy it you should be able to re-use it. – Furkan Yurdakul Aug 11 '20 at 08:32
  • Can you please try without removing the View of the ad? – android developer Aug 11 '20 at 09:03