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
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?
Is it ok to have the wrapper I've made?
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 calldestroy
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...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.
UnifiedNativeAdView
orUnifiedNativeAd
implicitly means you won't be able to create otherUnifiedNativeAdView
objects anymore using that ad, and, if you destroy the originalUnifiedNativeAd
object, theUnifiedNativeAdView
that uses the assets of thisUnifiedNativeAd
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 callingUnifiedNativeAdView.removeAllViews()
and then removing the view itself from its parent, but this might internally destroy theUnifiedNativeAd
, and that's something I don't know, you need to test it for yourself.This depends, ensuring not calling
destroy()
on either of the classes might be up to you, but in the future, they might add adestroy()
call on theUnifiedNativeAdView
object itself (for instance, the view'sonDetachedFromWindow
method). Since there isn't a function to see if the ad is destroyed with a method likeisDestroyed()
, 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.You can use a
Stack<UnifiedNativeAd>
or something to put the loaded ads on, and, while creating theUnifiedNativeAdView
object, you can callStack.pop()
so you know you already used the ad or the object doesn't exist anymore. But, you cannot use the sameUnifiedNativeAdView
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 fromUnifiedNativeAdView
since it internally destroys the native ad object anyway.UnifiedNativeAd
object, you should be able to use the same ad by inflating differentUnifiedNativeAdView
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!