简体   繁体   中英

How to properly handle the lifecycle of Admob's UnifiedNativeAd?

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)?

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM