From b7ac2aeb91946ec4a31583d5c1f54d42a99425c6 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Mon, 11 Nov 2024 13:23:59 +0100 Subject: [PATCH 01/16] feat: burl visibility tracker for original API --- .../main/java/org/prebid/mobile/AdUnit.java | 31 ++++ .../org/prebid/mobile/VisibilityMonitor.java | 138 ++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index 77ed24f79..d380d1bcd 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -24,6 +24,8 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; import androidx.annotation.IntRange; import androidx.annotation.NonNull; @@ -43,6 +45,7 @@ import org.prebid.mobile.rendering.sdk.PrebidContextHolder; import org.prebid.mobile.tasksmanager.TasksManager; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; @@ -65,6 +68,9 @@ public abstract class AdUnit { @Nullable protected BidResponse bidResponse; + protected final VisibilityMonitor visibilityMonitor = new VisibilityMonitor(); + protected WeakReference adViewReference = new WeakReference<>(null); + protected boolean allowNullableAdObject = false; public AdUnit(@NotNull String configId) { @@ -123,6 +129,7 @@ public void destroy() { if (bidLoader != null) { bidLoader.destroy(); } + visibilityMonitor.cancel(); } /** @@ -139,6 +146,12 @@ public void fetchDemand(@NonNull final OnCompleteListener2 listener) { }); } + public void fetchDemand(Object adObject, View adView, @NonNull OnCompleteListener listener) { + adViewReference = new WeakReference<>(adView); + visibilityMonitor.cancel(); + fetchDemand(adObject, listener); + } + /** * Loads ad and applies keywords to the ad object. * @@ -472,6 +485,8 @@ public void onFetchCompleted(BidResponse response) { HashMap keywords = response.getTargeting(); Util.apply(keywords, adObject); originalListener.onComplete(ResultCode.SUCCESS); + + registerVisibilityTrackerIfNeeded(bidResponse, adViewReference); } @Override @@ -517,5 +532,21 @@ public AdUnitConfiguration getConfiguration() { return configuration; } + private void registerVisibilityTrackerIfNeeded(BidResponse response, WeakReference adViewReference) { + visibilityMonitor.cancel(); + + if (response == null || response.getWinningBid() == null || response.getWinningBid().getBurl() == null) { + return; + } + + String burl = response.getWinningBid().getBurl(); + View adViewContainer = adViewReference != null ? adViewReference.get() : null; + if (adViewContainer == null) { + return; + } + + visibilityMonitor.trackView(adViewContainer, burl); + } + } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java new file mode 100644 index 000000000..3260bd050 --- /dev/null +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java @@ -0,0 +1,138 @@ +package org.prebid.mobile; + +import android.os.CountDownTimer; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebView; + +import androidx.annotation.Nullable; + +import org.jetbrains.annotations.NotNull; +import org.prebid.mobile.rendering.models.CreativeVisibilityTracker; +import org.prebid.mobile.rendering.models.internal.VisibilityTrackerOption; +import org.prebid.mobile.rendering.models.ntv.NativeEventTracker; +import org.prebid.mobile.rendering.networking.tracking.ServerConnection; +import org.prebid.mobile.rendering.sdk.PrebidContextHolder; + +import java.lang.ref.WeakReference; + +public class VisibilityMonitor { + + private final VisibilityTimer visibilityTimer = new VisibilityTimer(); + + public void trackView(@NotNull View adViewContainer, @NotNull String burl) { + visibilityTimer.start(adViewContainer, burl); + } + + public void cancel() { + visibilityTimer.destroy(); + } + + + private static class VisibilityTimer extends CountDownTimer { + + private static final int LONGEVITY = Integer.MAX_VALUE; + private static final int INTERVAL = 500; + + private int lastWebViewHash; + private String burl; + + private WeakReference containerViewReference; + @Nullable + private CreativeVisibilityTracker visibilityTracker; + + public VisibilityTimer() { + super(LONGEVITY, INTERVAL); + } + + public void start(View containerView, String burl) { + this.burl = burl; + this.containerViewReference = new WeakReference<>(containerView); + start(); + } + + @Override + public void onTick(long millisUntilFinished) { + View containerView = containerViewReference.get(); + if (containerView == null) { + cancel(); + return; + } + + WebView webView = findIn(containerView); + if (webView == null) { + return; + } + + if (lastWebViewHash == webView.hashCode()) { + Log.d("TESTV", "Ignored"); + return; + } + lastWebViewHash = webView.hashCode(); + + Log.d("TESTV", "Registering web view with hash: " + lastWebViewHash); + attachVisibilityTracker(webView); + cancel(); + LogUtil.info("Ad view impression tracker injected"); + } + + private void attachVisibilityTracker(WebView webView) { + if (visibilityTracker != null) { + visibilityTracker.stopVisibilityCheck(); + } + + visibilityTracker = new CreativeVisibilityTracker(webView, new VisibilityTrackerOption(NativeEventTracker.EventType.IMPRESSION)); + visibilityTracker.setVisibilityTrackerListener(result -> { + boolean visible = result.isVisible(); + if (visible) { + Log.d("TESTV", "FIRING BURL: " + burl); + ServerConnection.fireAndForget(burl); + visibilityTracker.stopVisibilityCheck(); + } + }); + visibilityTracker.startVisibilityCheck(PrebidContextHolder.getContext()); + } + + @Override + public void onFinish() { + } + + public void destroy() { + if (visibilityTracker != null) { + visibilityTracker.stopVisibilityCheck(); + } + cancel(); + } + + public static WebView findIn(View root) { + if (root instanceof WebView) { + return (WebView) root; + } + + if (root instanceof ViewGroup) { + return findRecursively((ViewGroup) root); + } + + return null; + } + + private static WebView findRecursively(ViewGroup root) { + for (int i = 0; i < root.getChildCount(); i++) { + View child = root.getChildAt(i); + if (child instanceof WebView) { + return (WebView) child; + } + + if (child instanceof ViewGroup) { + WebView result = findRecursively((ViewGroup) child); + if (result != null) { + return result; + } + } + } + return null; + } + } + +} From 1cd1073558e13767baf103fc0b086a7083cc39b3 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Mon, 11 Nov 2024 13:55:00 +0100 Subject: [PATCH 02/16] feat: correction for GAM auto refresh More verbose logs. --- .../java/org/prebid/mobile/VisibilityMonitor.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java index 3260bd050..ef657f0c3 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java @@ -22,6 +22,7 @@ public class VisibilityMonitor { private final VisibilityTimer visibilityTimer = new VisibilityTimer(); public void trackView(@NotNull View adViewContainer, @NotNull String burl) { + visibilityTimer.destroy(); visibilityTimer.start(adViewContainer, burl); } @@ -34,6 +35,7 @@ private static class VisibilityTimer extends CountDownTimer { private static final int LONGEVITY = Integer.MAX_VALUE; private static final int INTERVAL = 500; + private static final String TAG = "VisibilityTimer"; private int lastWebViewHash; private String burl; @@ -57,6 +59,7 @@ public void onTick(long millisUntilFinished) { View containerView = containerViewReference.get(); if (containerView == null) { cancel(); + LogUtil.debug(TAG, "Cancelled due to ad view is null"); return; } @@ -66,15 +69,12 @@ public void onTick(long millisUntilFinished) { } if (lastWebViewHash == webView.hashCode()) { - Log.d("TESTV", "Ignored"); return; } lastWebViewHash = webView.hashCode(); - Log.d("TESTV", "Registering web view with hash: " + lastWebViewHash); attachVisibilityTracker(webView); - cancel(); - LogUtil.info("Ad view impression tracker injected"); + LogUtil.debug(TAG, "Registering the new WebView: " + lastWebViewHash); } private void attachVisibilityTracker(WebView webView) { @@ -86,7 +86,7 @@ private void attachVisibilityTracker(WebView webView) { visibilityTracker.setVisibilityTrackerListener(result -> { boolean visible = result.isVisible(); if (visible) { - Log.d("TESTV", "FIRING BURL: " + burl); + LogUtil.debug(TAG, "View is visible. Firing event: " + burl); ServerConnection.fireAndForget(burl); visibilityTracker.stopVisibilityCheck(); } @@ -100,7 +100,9 @@ public void onFinish() { public void destroy() { if (visibilityTracker != null) { + LogUtil.debug(TAG, "Destroying"); visibilityTracker.stopVisibilityCheck(); + visibilityTracker = null; } cancel(); } From 320b5dc184b2f04ffde23a3a5a24eb1c1ecf7bd3 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 12 Nov 2024 13:15:20 +0100 Subject: [PATCH 03/16] feat: compare response cache id with creative cache id to track visibility --- .../main/java/org/prebid/mobile/AdUnit.java | 8 ++- .../org/prebid/mobile/VisibilityMonitor.java | 27 +++++++--- .../prebid/mobile/addendum/AdViewUtils.java | 50 +++++++++++++++++-- 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index d380d1bcd..1347128a5 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -545,7 +545,13 @@ private void registerVisibilityTrackerIfNeeded(BidResponse response, WeakReferen return; } - visibilityMonitor.trackView(adViewContainer, burl); + String cacheId = response.getTargeting().get("hb_cache_id"); + if (cacheId == null) { + LogUtil.warning("Can't register visibility tracker. There is no hb_cache_id keyword."); + return; + } + + visibilityMonitor.trackView(adViewContainer, burl, cacheId); } } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java index ef657f0c3..873719c55 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java @@ -1,7 +1,6 @@ package org.prebid.mobile; import android.os.CountDownTimer; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; @@ -9,6 +8,7 @@ import androidx.annotation.Nullable; import org.jetbrains.annotations.NotNull; +import org.prebid.mobile.addendum.AdViewUtils; import org.prebid.mobile.rendering.models.CreativeVisibilityTracker; import org.prebid.mobile.rendering.models.internal.VisibilityTrackerOption; import org.prebid.mobile.rendering.models.ntv.NativeEventTracker; @@ -21,9 +21,9 @@ public class VisibilityMonitor { private final VisibilityTimer visibilityTimer = new VisibilityTimer(); - public void trackView(@NotNull View adViewContainer, @NotNull String burl) { + public void trackView(@NotNull View adViewContainer, @NotNull String burl, @NotNull String cacheId) { visibilityTimer.destroy(); - visibilityTimer.start(adViewContainer, burl); + visibilityTimer.start(adViewContainer, burl, cacheId); } public void cancel() { @@ -39,6 +39,7 @@ private static class VisibilityTimer extends CountDownTimer { private int lastWebViewHash; private String burl; + private String responseCacheId; private WeakReference containerViewReference; @Nullable @@ -48,8 +49,9 @@ public VisibilityTimer() { super(LONGEVITY, INTERVAL); } - public void start(View containerView, String burl) { + public void start(View containerView, String burl, String cacheId) { this.burl = burl; + this.responseCacheId = cacheId; this.containerViewReference = new WeakReference<>(containerView); start(); } @@ -71,10 +73,21 @@ public void onTick(long millisUntilFinished) { if (lastWebViewHash == webView.hashCode()) { return; } - lastWebViewHash = webView.hashCode(); - attachVisibilityTracker(webView); - LogUtil.debug(TAG, "Registering the new WebView: " + lastWebViewHash); + AdViewUtils.findCacheId(webView, cacheId -> { + if (cacheId == null || cacheId.isEmpty()) { + return; + } + + if (!cacheId.equals(responseCacheId)) { + LogUtil.warning(TAG, "Different cache ids;"); + return; + } + + lastWebViewHash = webView.hashCode(); + attachVisibilityTracker(webView); + LogUtil.debug(TAG, "Registering the new WebView: " + lastWebViewHash); + }); } private void attachVisibilityTracker(WebView webView) { diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/addendum/AdViewUtils.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/addendum/AdViewUtils.java index 4d6c677b0..298e950ad 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/addendum/AdViewUtils.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/addendum/AdViewUtils.java @@ -23,9 +23,11 @@ import android.view.ViewGroup; import android.webkit.ValueCallback; import android.webkit.WebView; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.Size; + import org.prebid.mobile.CacheManager; import org.prebid.mobile.LogUtil; import org.prebid.mobile.PrebidNativeAd; @@ -33,22 +35,35 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; public final class AdViewUtils { + /** + * Escaped double quotes. + */ + private static final String EDQ = "\\\\\""; + private static final String INNER_HTML_SCRIPT = "document.body.innerHTML"; private static final String SIZE_VALUE_REGEX_EXPRESSION = "[0-9]+x[0-9]+"; private static final String SIZE_OBJECT_REGEX_EXPRESSION = "hb_size\\W+" + SIZE_VALUE_REGEX_EXPRESSION; //"hb_size\\W+[0-9]+x[0-9]+" + private static final String CACHE_ID_REGEX = EDQ + "hb_cache_id" + EDQ + ":\\[" + EDQ + "(.*?)" + EDQ + "\\]"; + + private static final String GAM_VIEW_CLASS = "com.google.android.gms.ads.doubleclick.PublisherAdView"; private static final String GAM_VIEW_CLASS_2 = "com.google.android.gms.ads.admanager.AdManagerAdView"; private static final String GAM_CUSTOM_TEMPLATE_AD_CLASS = "com.google.android.gms.ads.formats.NativeCustomTemplateAd"; private static final String GAM_CUSTOM_TEMPLATE_AD_CLASS_2 = "com.google.android.gms.ads.nativead.NativeCustomFormatAd"; - private AdViewUtils() { } + private AdViewUtils() { + } public static void findPrebidCreativeSize(@Nullable View adView, final PbFindSizeListener handler) { if (adView == null) { @@ -75,6 +90,7 @@ static void triggerSuccess(WebView webView, Pair adSize, PbFin fixZoomIn(webView, width, height); } + //a fix of strange bug on Android with image scaling up //case: should be called after PublisherAdView.setAdSizes() static void fixZoomIn(final WebView webView, final int expectedWidth, final int expectedHeight) { @@ -356,6 +372,29 @@ static String matchAndCheck(String regex, String text) { return firstResult; } + public static void findCacheId(WebView webView, CacheIdResult onResult) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + onResult.run(null); + return; + } + + webView.evaluateJavascript(INNER_HTML_SCRIPT, value -> { + String result = findCacheId(value); + onResult.run(result); + }); + } + + @Nullable + static String findCacheId(String html) { + Pattern pattern = Pattern.compile(CACHE_ID_REGEX); + Matcher matcher = pattern.matcher(html); + + if (!matcher.find() || matcher.groupCount() == 0) { + return null; + } + return matcher.group(1); + } + @Nullable static Pair stringToSize(String size) { String[] sizeArr = size.split("x"); @@ -469,12 +508,17 @@ static Object callMethodOnObject(Object object, String methodName, Object... par return null; } + public interface CacheIdResult { + void run(String cacheId); + } + } //It is not possible to use Enum because we should have a possibility to pass additional information final class PbFindSizeErrorFactory { - private PbFindSizeErrorFactory() { } + private PbFindSizeErrorFactory() { + } //common errors static final int UNSPECIFIED_CODE = 201; From 823713ca9e9f3f7cc88b3a15b33590a4a3b0958d Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Wed, 13 Nov 2024 14:15:51 +0100 Subject: [PATCH 04/16] feat: interstitial visibility tracker --- .../main/java/org/prebid/mobile/AdUnit.java | 50 +++++++++++++++---- .../org/prebid/mobile/InterstitialAdUnit.java | 4 ++ .../mobile/VisibilityActivityListener.java | 46 +++++++++++++++++ .../org/prebid/mobile/VisibilityMonitor.java | 29 +++++++++-- 4 files changed, 114 insertions(+), 15 deletions(-) create mode 100644 PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityActivityListener.java diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index 1347128a5..f137f260e 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -19,13 +19,15 @@ import static org.prebid.mobile.PrebidMobile.AUTO_REFRESH_DELAY_MAX; import static org.prebid.mobile.PrebidMobile.AUTO_REFRESH_DELAY_MIN; +import android.app.Activity; +import android.app.Application; import android.content.Context; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; +import android.os.Bundle; import android.text.TextUtils; import android.view.View; -import android.view.ViewGroup; import androidx.annotation.IntRange; import androidx.annotation.NonNull; @@ -72,6 +74,7 @@ public abstract class AdUnit { protected WeakReference adViewReference = new WeakReference<>(null); protected boolean allowNullableAdObject = false; + protected boolean useInterstitialVisibilityTracker = false; public AdUnit(@NotNull String configId) { configuration.setConfigId(configId); @@ -129,7 +132,7 @@ public void destroy() { if (bidLoader != null) { bidLoader.destroy(); } - visibilityMonitor.cancel(); + visibilityMonitor.stopTracking(); } /** @@ -146,9 +149,17 @@ public void fetchDemand(@NonNull final OnCompleteListener2 listener) { }); } + /** + * Loads ad and applies keywords to the ad object. + * Fetch demand with the visibility tracking for the + * + * @param adObject AdMob's ({@code AdManagerAdRequest} or {@code AdManagerAdRequest.Builder}) + * or AppLovin's ({@code MaxNativeAdLoader}) ad object + * @param adView the ad view object (f.e. {@code AdManagerAdView}) + * @param listener callback when operation is completed (success or fail) + */ public void fetchDemand(Object adObject, View adView, @NonNull OnCompleteListener listener) { adViewReference = new WeakReference<>(adView); - visibilityMonitor.cancel(); fetchDemand(adObject, listener); } @@ -160,6 +171,8 @@ public void fetchDemand(Object adObject, View adView, @NonNull OnCompleteListene * @param listener callback when operation is completed (success or fail) */ public void fetchDemand(Object adObject, @NonNull OnCompleteListener listener) { + visibilityMonitor.stopTracking(); + if (TextUtils.isEmpty(PrebidMobile.getPrebidServerAccountId())) { LogUtil.error("Empty account id."); listener.onComplete(ResultCode.INVALID_ACCOUNT_ID); @@ -486,7 +499,7 @@ public void onFetchCompleted(BidResponse response) { Util.apply(keywords, adObject); originalListener.onComplete(ResultCode.SUCCESS); - registerVisibilityTrackerIfNeeded(bidResponse, adViewReference); + registerVisibilityTrackerIfNeeded(bidResponse); } @Override @@ -532,18 +545,13 @@ public AdUnitConfiguration getConfiguration() { return configuration; } - private void registerVisibilityTrackerIfNeeded(BidResponse response, WeakReference adViewReference) { - visibilityMonitor.cancel(); + private void registerVisibilityTrackerIfNeeded(BidResponse response) { + visibilityMonitor.stopTracking(); if (response == null || response.getWinningBid() == null || response.getWinningBid().getBurl() == null) { return; } - String burl = response.getWinningBid().getBurl(); - View adViewContainer = adViewReference != null ? adViewReference.get() : null; - if (adViewContainer == null) { - return; - } String cacheId = response.getTargeting().get("hb_cache_id"); if (cacheId == null) { @@ -551,8 +559,28 @@ private void registerVisibilityTrackerIfNeeded(BidResponse response, WeakReferen return; } + boolean isBannerTracker = !useInterstitialVisibilityTracker; + if (isBannerTracker) { + bannerVisibilityTracker(burl, cacheId); + } else { + interstitialVisibilityTracker(burl, cacheId); + } + } + + private void bannerVisibilityTracker(String burl, String cacheId) { + View adViewContainer = adViewReference != null ? adViewReference.get() : null; + if (adViewContainer == null) { + return; + } + visibilityMonitor.trackView(adViewContainer, burl, cacheId); } + private void interstitialVisibilityTracker(String burl, String cacheId) { + + + visibilityMonitor.trackInterstitial(burl, cacheId); + } + } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java index e58ca32d9..ec08331cb 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java @@ -70,4 +70,8 @@ public void setMinSizePercentage( configuration.setMinSizePercentage(new AdSize(width, height)); } + public void useInterstitialVisibilityTracker(boolean enable) { + this.useInterstitialVisibilityTracker = enable; + } + } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityActivityListener.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityActivityListener.java new file mode 100644 index 000000000..137ba4d6d --- /dev/null +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityActivityListener.java @@ -0,0 +1,46 @@ +package org.prebid.mobile; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class VisibilityActivityListener implements Application.ActivityLifecycleCallbacks { + + private final VisibilityMonitor monitor; + private final String burl; + private final String cacheId; + + public VisibilityActivityListener(VisibilityMonitor monitor, String burl, String cacheId) { + this.monitor = monitor; + this.burl = burl; + this.cacheId = cacheId; + } + + @Override + public void onActivityResumed(@NonNull Activity activity) { + View rootView = activity.getWindow().getDecorView(); + monitor.trackView(rootView, burl, cacheId); + } + + @Override + public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {} + + @Override + public void onActivityStarted(@NonNull Activity activity) {} + + @Override + public void onActivityPaused(@NonNull Activity activity) {} + + @Override + public void onActivityStopped(@NonNull Activity activity) {} + + @Override + public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {} + + @Override + public void onActivityDestroyed(@NonNull Activity activity) {} +} diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java index 873719c55..a7d172c20 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java @@ -1,5 +1,7 @@ package org.prebid.mobile; +import android.app.Application; +import android.content.Context; import android.os.CountDownTimer; import android.view.View; import android.view.ViewGroup; @@ -21,15 +23,34 @@ public class VisibilityMonitor { private final VisibilityTimer visibilityTimer = new VisibilityTimer(); + @Nullable + private VisibilityActivityListener activityListener; + public void trackView(@NotNull View adViewContainer, @NotNull String burl, @NotNull String cacheId) { - visibilityTimer.destroy(); + stopTracking(); + visibilityTimer.start(adViewContainer, burl, cacheId); } - public void cancel() { + public void trackInterstitial(String burl, String cacheId) { + stopTracking(); + + activityListener = new VisibilityActivityListener(this, burl, cacheId); + getApplication().registerActivityLifecycleCallbacks(activityListener); + } + + public void stopTracking() { visibilityTimer.destroy(); + + if (activityListener != null) { + getApplication().unregisterActivityLifecycleCallbacks(activityListener); + } } + private Application getApplication() { + Context context = PrebidContextHolder.getContext(); + return (Application) context; + } private static class VisibilityTimer extends CountDownTimer { @@ -73,6 +94,7 @@ public void onTick(long millisUntilFinished) { if (lastWebViewHash == webView.hashCode()) { return; } + lastWebViewHash = webView.hashCode(); AdViewUtils.findCacheId(webView, cacheId -> { if (cacheId == null || cacheId.isEmpty()) { @@ -80,11 +102,10 @@ public void onTick(long millisUntilFinished) { } if (!cacheId.equals(responseCacheId)) { - LogUtil.warning(TAG, "Different cache ids;"); + LogUtil.warning(TAG, "Different cache ids"); return; } - lastWebViewHash = webView.hashCode(); attachVisibilityTracker(webView); LogUtil.debug(TAG, "Registering the new WebView: " + lastWebViewHash); }); From 3585ff3830b285e17c1810f8d3f74b980f42e328 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Thu, 14 Nov 2024 10:00:01 +0100 Subject: [PATCH 05/16] feat: stop interstitial tracker after first finding --- .../src/main/java/org/prebid/mobile/AdUnit.java | 5 +---- .../java/org/prebid/mobile/VisibilityMonitor.java | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index f137f260e..5f484c73f 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -74,7 +74,6 @@ public abstract class AdUnit { protected WeakReference adViewReference = new WeakReference<>(null); protected boolean allowNullableAdObject = false; - protected boolean useInterstitialVisibilityTracker = false; public AdUnit(@NotNull String configId) { configuration.setConfigId(configId); @@ -559,7 +558,7 @@ private void registerVisibilityTrackerIfNeeded(BidResponse response) { return; } - boolean isBannerTracker = !useInterstitialVisibilityTracker; + boolean isBannerTracker = !(this instanceof InterstitialAdUnit); if (isBannerTracker) { bannerVisibilityTracker(burl, cacheId); } else { @@ -577,8 +576,6 @@ private void bannerVisibilityTracker(String burl, String cacheId) { } private void interstitialVisibilityTracker(String burl, String cacheId) { - - visibilityMonitor.trackInterstitial(burl, cacheId); } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java index a7d172c20..a2f5c070d 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java @@ -3,6 +3,7 @@ import android.app.Application; import android.content.Context; import android.os.CountDownTimer; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; @@ -21,6 +22,8 @@ public class VisibilityMonitor { + private boolean stopAfterFirstFinding = false; + private final VisibilityTimer visibilityTimer = new VisibilityTimer(); @Nullable @@ -29,12 +32,13 @@ public class VisibilityMonitor { public void trackView(@NotNull View adViewContainer, @NotNull String burl, @NotNull String cacheId) { stopTracking(); - visibilityTimer.start(adViewContainer, burl, cacheId); + visibilityTimer.start(adViewContainer, burl, cacheId, stopAfterFirstFinding); } public void trackInterstitial(String burl, String cacheId) { stopTracking(); + stopAfterFirstFinding = true; activityListener = new VisibilityActivityListener(this, burl, cacheId); getApplication().registerActivityLifecycleCallbacks(activityListener); } @@ -59,6 +63,7 @@ private static class VisibilityTimer extends CountDownTimer { private static final String TAG = "VisibilityTimer"; private int lastWebViewHash; + private boolean stopAfterFirstFinding; private String burl; private String responseCacheId; @@ -70,10 +75,11 @@ public VisibilityTimer() { super(LONGEVITY, INTERVAL); } - public void start(View containerView, String burl, String cacheId) { + public void start(View containerView, String burl, String cacheId, boolean stopAfterFirstFinding) { this.burl = burl; this.responseCacheId = cacheId; this.containerViewReference = new WeakReference<>(containerView); + this.stopAfterFirstFinding = stopAfterFirstFinding; start(); } @@ -96,6 +102,11 @@ public void onTick(long millisUntilFinished) { } lastWebViewHash = webView.hashCode(); + if (stopAfterFirstFinding) { + Log.d(TAG, "Interstitial WebView found. Stopping..."); + cancel(); + } + AdViewUtils.findCacheId(webView, cacheId -> { if (cacheId == null || cacheId.isEmpty()) { return; From 447b5d4cc430f22b136846ab253fa029d2bdf587 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Thu, 14 Nov 2024 11:27:07 +0100 Subject: [PATCH 06/16] feat: replace stopAutoRefresh() to destroy() in test examples --- .../ads/gam/original/GamOriginalApiDisplayBanner300x250.java | 2 +- .../ads/gam/original/GamOriginalApiDisplayBanner320x50.java | 2 +- .../ads/gam/original/GamOriginalApiDisplayInterstitial.java | 2 +- .../ads/gam/original/GamOriginalApiMultiformatBanner.java | 2 +- .../ads/gam/original/GamOriginalApiMultiformatInterstitial.java | 2 +- .../activities/ads/gam/original/GamOriginalApiNativeInApp.java | 2 +- .../activities/ads/gam/original/GamOriginalApiNativeStyles.java | 2 +- .../activities/ads/gam/original/GamOriginalApiVideoBanner.java | 2 +- .../ads/gam/original/GamOriginalApiVideoInStream.java | 2 +- .../ads/gam/original/GamOriginalApiVideoInterstitial.java | 2 +- .../ads/gam/original/GamOriginalApiVideoRewarded.java | 2 +- .../gam/original/GamOriginalApiDisplayBanner300x250Activity.kt | 2 +- .../gam/original/GamOriginalApiDisplayBanner320x50Activity.kt | 2 +- .../original/GamOriginalApiDisplayBannerMultiSizeActivity.kt | 2 +- .../gam/original/GamOriginalApiDisplayInterstitialActivity.kt | 2 +- .../ads/gam/original/GamOriginalApiInStreamActivity.kt | 2 +- .../ads/gam/original/GamOriginalApiMultiformatBannerActivity.kt | 2 +- .../original/GamOriginalApiMultiformatInterstitialActivity.kt | 2 +- .../ads/gam/original/GamOriginalApiNativeInAppActivity.kt | 2 +- .../ads/gam/original/GamOriginalApiNativeStylesActivity.kt | 2 +- .../ads/gam/original/GamOriginalApiVideoInterstitialActivity.kt | 2 +- .../ads/gam/original/GamOriginalApiVideoRewardedActivity.kt | 2 +- .../plugplay/bidding/gam/original/GamOriginalBannerFragment.kt | 2 +- .../bidding/gam/original/GamOriginalInstreamFragment.kt | 2 +- .../bidding/gam/original/GamOriginalInstreamNewApiFragment.kt | 2 +- .../bidding/gam/original/GamOriginalNativeBannerFragment.kt | 2 +- .../bidding/gam/original/GamOriginalNativeInAppFragment.kt | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayBanner300x250.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayBanner300x250.java index a5c146962..e602b13df 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayBanner300x250.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayBanner300x250.java @@ -85,7 +85,7 @@ public void failure(@NonNull PbFindSizeError error) { protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } } } diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50.java index 4691eb8a0..d39b51e55 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50.java @@ -100,7 +100,7 @@ private void setOpenRtbConfig() { protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } } } diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayInterstitial.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayInterstitial.java index cb66ff468..3f977e099 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayInterstitial.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiDisplayInterstitial.java @@ -59,7 +59,7 @@ protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } } } diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiMultiformatBanner.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiMultiformatBanner.java index f45e3f479..18a4f5a14 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiMultiformatBanner.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiMultiformatBanner.java @@ -98,7 +98,7 @@ public void failure(@NonNull PbFindSizeError error) { protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } } } diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiMultiformatInterstitial.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiMultiformatInterstitial.java index 43e61a5c2..52a63a878 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiMultiformatInterstitial.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiMultiformatInterstitial.java @@ -72,7 +72,7 @@ protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } } } diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiNativeInApp.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiNativeInApp.java index 2c8332c06..a45ba5176 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiNativeInApp.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiNativeInApp.java @@ -188,7 +188,7 @@ protected void onDestroy() { adView.destroy(); } if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } if (unifiedNativeAd != null) { unifiedNativeAd.destroy(); diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiNativeStyles.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiNativeStyles.java index 566ffba46..6c6276335 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiNativeStyles.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiNativeStyles.java @@ -94,7 +94,7 @@ private void configureNativeAdUnit(NativeAdUnit adUnit) { protected void onDestroy() { super.onDestroy(); if (nativeAdUnit != null) { - nativeAdUnit.stopAutoRefresh(); + nativeAdUnit.destroy(); } } } diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoBanner.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoBanner.java index 8cfe13d21..56826a84f 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoBanner.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoBanner.java @@ -89,7 +89,7 @@ protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } } } diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoInStream.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoInStream.java index 47ffa41a7..ca952e8e8 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoInStream.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoInStream.java @@ -101,7 +101,7 @@ protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } if (adsLoader != null) { adsLoader.setPlayer(null); diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoInterstitial.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoInterstitial.java index c7064e6f3..0e0bdcfb5 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoInterstitial.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoInterstitial.java @@ -71,7 +71,7 @@ public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) { protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } } } diff --git a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoRewarded.java b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoRewarded.java index ce2814afe..7b1601415 100644 --- a/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoRewarded.java +++ b/Example/PrebidDemoJava/src/main/java/org/prebid/mobile/javademo/activities/ads/gam/original/GamOriginalApiVideoRewarded.java @@ -66,7 +66,7 @@ public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) { protected void onDestroy() { super.onDestroy(); if (adUnit != null) { - adUnit.stopAutoRefresh(); + adUnit.destroy(); } } } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner300x250Activity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner300x250Activity.kt index 971b45987..5ad1ebff6 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner300x250Activity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner300x250Activity.kt @@ -76,7 +76,7 @@ class GamOriginalApiDisplayBanner300x250Activity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } private fun createGAMListener(adView: AdManagerAdView): AdListener { diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt index 6d2eca207..f07504907 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt @@ -95,7 +95,7 @@ class GamOriginalApiDisplayBanner320x50Activity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBannerMultiSizeActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBannerMultiSizeActivity.kt index 5583f4832..7c0fbf10a 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBannerMultiSizeActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBannerMultiSizeActivity.kt @@ -83,7 +83,7 @@ class GamOriginalApiDisplayBannerMultiSizeActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt index c5374e451..73738a2d9 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt @@ -78,6 +78,6 @@ class GamOriginalApiDisplayInterstitialActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiInStreamActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiInStreamActivity.kt index 94a39e1a2..f34b2f816 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiInStreamActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiInStreamActivity.kt @@ -137,7 +137,7 @@ class GamOriginalApiInStreamActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() adsLoader?.setPlayer(null) adsLoader?.release() player?.release() diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiMultiformatBannerActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiMultiformatBannerActivity.kt index 9443a9da6..7fe378280 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiMultiformatBannerActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiMultiformatBannerActivity.kt @@ -87,7 +87,7 @@ class GamOriginalApiMultiformatBannerActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } private fun createGAMListener(adView: AdManagerAdView): AdListener { diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiMultiformatInterstitialActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiMultiformatInterstitialActivity.kt index 265327de9..fa4f66898 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiMultiformatInterstitialActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiMultiformatInterstitialActivity.kt @@ -91,6 +91,6 @@ class GamOriginalApiMultiformatInterstitialActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiNativeInAppActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiNativeInAppActivity.kt index 607981d8a..89656fdef 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiNativeInAppActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiNativeInAppActivity.kt @@ -212,7 +212,7 @@ class GamOriginalApiNativeInAppActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() adView?.destroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() unifiedNativeAd?.destroy() } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiNativeStylesActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiNativeStylesActivity.kt index ce5bede0b..765c6c36f 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiNativeStylesActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiNativeStylesActivity.kt @@ -93,7 +93,7 @@ class GamOriginalApiNativeStylesActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - nativeAdUnit?.stopAutoRefresh() + nativeAdUnit?.destroy() } } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiVideoInterstitialActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiVideoInterstitialActivity.kt index f18e605c3..8b42eb9fa 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiVideoInterstitialActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiVideoInterstitialActivity.kt @@ -89,7 +89,7 @@ class GamOriginalApiVideoInterstitialActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiVideoRewardedActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiVideoRewardedActivity.kt index af01ad518..28248be3b 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiVideoRewardedActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiVideoRewardedActivity.kt @@ -74,7 +74,7 @@ class GamOriginalApiVideoRewardedActivity : BaseAdActivity() { override fun onDestroy() { super.onDestroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } } diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalBannerFragment.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalBannerFragment.kt index ad5fd724d..9106bccc3 100644 --- a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalBannerFragment.kt +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalBannerFragment.kt @@ -125,7 +125,7 @@ open class GamOriginalBannerFragment : AdFragment() { override fun onDestroyView() { super.onDestroyView() adView?.destroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() } private class Events(parentView: View) : BaseEvents(parentView) { diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalInstreamFragment.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalInstreamFragment.kt index d6a94ef98..09a90229c 100644 --- a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalInstreamFragment.kt +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalInstreamFragment.kt @@ -101,7 +101,7 @@ class GamOriginalInstreamFragment : AdFragment() { override fun onDestroyView() { super.onDestroyView() - adUnit?.stopAutoRefresh() + adUnit?.destroy() adsLoader?.setPlayer(null) adsLoader?.release() player?.release() diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalInstreamNewApiFragment.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalInstreamNewApiFragment.kt index 7e3124d5a..9182d33b7 100644 --- a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalInstreamNewApiFragment.kt +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalInstreamNewApiFragment.kt @@ -102,7 +102,7 @@ class GamOriginalInstreamNewApiFragment : AdFragment() { override fun onDestroyView() { super.onDestroyView() - adUnit?.stopAutoRefresh() + adUnit?.destroy() adsLoader?.setPlayer(null) adsLoader?.release() player?.release() diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalNativeBannerFragment.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalNativeBannerFragment.kt index dbe135ea0..06234b3eb 100644 --- a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalNativeBannerFragment.kt +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalNativeBannerFragment.kt @@ -144,7 +144,7 @@ class GamOriginalNativeBannerFragment : AdFragment() { override fun onDestroy() { super.onDestroy() - nativeAdUnit?.stopAutoRefresh() + nativeAdUnit?.destroy() } private class Events(parentView: View) : BaseEvents(parentView) { diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalNativeInAppFragment.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalNativeInAppFragment.kt index 0123888f2..f099f5aeb 100644 --- a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalNativeInAppFragment.kt +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/gam/original/GamOriginalNativeInAppFragment.kt @@ -222,7 +222,7 @@ class GamOriginalNativeInAppFragment : PpmNativeFragment() { override fun onDestroy() { super.onDestroy() adView?.destroy() - adUnit?.stopAutoRefresh() + adUnit?.destroy() unifiedNativeAd?.destroy() } } \ No newline at end of file From 5a907ea5dd0a1b04793a8bdf45bd8926de25be0d Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Thu, 14 Nov 2024 14:43:08 +0100 Subject: [PATCH 07/16] feat: ignore VAST creatives --- .../src/main/java/org/prebid/mobile/AdUnit.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index 5f484c73f..41f24fda4 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -61,6 +61,8 @@ */ public abstract class AdUnit { + private static final String TAG = "AdUnit"; + protected AdUnitConfiguration configuration = new AdUnitConfiguration(); @Nullable @@ -550,11 +552,16 @@ private void registerVisibilityTrackerIfNeeded(BidResponse response) { if (response == null || response.getWinningBid() == null || response.getWinningBid().getBurl() == null) { return; } + if (response.isVideo()) { + LogUtil.debug(TAG, "VisibilityTracker ignored due to the video ad"); + return; + } + String burl = response.getWinningBid().getBurl(); String cacheId = response.getTargeting().get("hb_cache_id"); if (cacheId == null) { - LogUtil.warning("Can't register visibility tracker. There is no hb_cache_id keyword."); + LogUtil.warning(TAG, "Can't register visibility tracker. There is no hb_cache_id keyword."); return; } From 68e793d20cbbdba0c25677db7159ae242ac9a468 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Thu, 14 Nov 2024 16:37:56 +0100 Subject: [PATCH 08/16] feat: protect cache id listener with weak reference --- .../org/prebid/mobile/VisibilityMonitor.java | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java index a2f5c070d..75862e6dc 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java @@ -80,6 +80,8 @@ public void start(View containerView, String burl, String cacheId, boolean stopA this.responseCacheId = cacheId; this.containerViewReference = new WeakReference<>(containerView); this.stopAfterFirstFinding = stopAfterFirstFinding; + + LogUtil.debug(TAG, "Start of monitoring..."); start(); } @@ -87,8 +89,8 @@ public void start(View containerView, String burl, String cacheId, boolean stopA public void onTick(long millisUntilFinished) { View containerView = containerViewReference.get(); if (containerView == null) { - cancel(); LogUtil.debug(TAG, "Cancelled due to ad view is null"); + destroy(); return; } @@ -103,23 +105,14 @@ public void onTick(long millisUntilFinished) { lastWebViewHash = webView.hashCode(); if (stopAfterFirstFinding) { - Log.d(TAG, "Interstitial WebView found. Stopping..."); - cancel(); + LogUtil.debug(TAG, "Interstitial WebView found. Stopping..."); + destroy(); } - AdViewUtils.findCacheId(webView, cacheId -> { - if (cacheId == null || cacheId.isEmpty()) { - return; - } - - if (!cacheId.equals(responseCacheId)) { - LogUtil.warning(TAG, "Different cache ids"); - return; - } - - attachVisibilityTracker(webView); - LogUtil.debug(TAG, "Registering the new WebView: " + lastWebViewHash); - }); + AdViewUtils.findCacheId( + webView, + attachVisibilityTrackerTask(new WeakReference<>(webView), this, responseCacheId, lastWebViewHash) + ); } private void attachVisibilityTracker(WebView webView) { @@ -180,6 +173,27 @@ private static WebView findRecursively(ViewGroup root) { } return null; } + + private static AdViewUtils.CacheIdResult attachVisibilityTrackerTask(WeakReference webViewReference, VisibilityTimer visibilityTimer, String responseCacheId, int lastWebViewHash) { + return cacheId -> { + if (cacheId == null || cacheId.isEmpty()) { + return; + } + + if (!cacheId.equals(responseCacheId)) { + LogUtil.warning(TAG, "Different cache ids"); + return; + } + + WebView webView = webViewReference.get(); + if (webView == null) { + return; + } + + visibilityTimer.attachVisibilityTracker(webView); + LogUtil.debug(TAG, "Registering the new WebView: " + lastWebViewHash); + }; + } } } From 3482bd9b382ad6594a7cbd1d4b7b53dbc6f5fe03 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Fri, 15 Nov 2024 11:34:36 +0100 Subject: [PATCH 09/16] feat: boolean activator for enabling the interstitial impression tracking --- .../original/GamOriginalApiDisplayBanner320x50Activity.kt | 2 +- .../original/GamOriginalApiDisplayInterstitialActivity.kt | 5 ++++- .../src/main/java/org/prebid/mobile/AdUnit.java | 3 ++- .../src/main/java/org/prebid/mobile/InterstitialAdUnit.java | 4 ++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt index f07504907..2fc0c8c1f 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt @@ -73,7 +73,7 @@ class GamOriginalApiDisplayBanner320x50Activity : BaseAdActivity() { adUnit?.bannerParameters = parameters adUnit?.setAutoRefreshInterval(refreshTimeSeconds) - adUnit?.fetchDemand(request) { + adUnit?.fetchDemand(request, adView) { adView.loadAd(request) } } diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt index 73738a2d9..8f3ebec5b 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt @@ -32,7 +32,7 @@ class GamOriginalApiDisplayInterstitialActivity : BaseAdActivity() { const val CONFIG_ID = "prebid-demo-display-interstitial-320-480" } - private var adUnit: AdUnit? = null + private var adUnit: InterstitialAdUnit? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -45,6 +45,9 @@ class GamOriginalApiDisplayInterstitialActivity : BaseAdActivity() { // 1. Create InterstitialAdUnit adUnit = InterstitialAdUnit(CONFIG_ID, 80, 60) + // Activate additional impression tracker (for burl) + adUnit?.activatePrebidImpressionTracker(true) + // 2. Make a bid request to Prebid Server val request = AdManagerAdRequest.Builder().build() adUnit?.fetchDemand(request) { diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index 41f24fda4..a385c6beb 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -76,6 +76,7 @@ public abstract class AdUnit { protected WeakReference adViewReference = new WeakReference<>(null); protected boolean allowNullableAdObject = false; + protected boolean activatePrebidImpressionTracker = false; public AdUnit(@NotNull String configId) { configuration.setConfigId(configId); @@ -568,7 +569,7 @@ private void registerVisibilityTrackerIfNeeded(BidResponse response) { boolean isBannerTracker = !(this instanceof InterstitialAdUnit); if (isBannerTracker) { bannerVisibilityTracker(burl, cacheId); - } else { + } else if (activatePrebidImpressionTracker) { interstitialVisibilityTracker(burl, cacheId); } } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java index ec08331cb..793491eda 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java @@ -74,4 +74,8 @@ public void useInterstitialVisibilityTracker(boolean enable) { this.useInterstitialVisibilityTracker = enable; } + public void activatePrebidImpressionTracker(boolean activate) { + this.activatePrebidImpressionTracker = activate; + } + } From ceb37d9aa965854c95abf0eccda51db374a721b2 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Wed, 20 Nov 2024 19:48:20 +0100 Subject: [PATCH 10/16] feat: move impression tracker from fetch demand --- ...mOriginalApiDisplayBanner320x50Activity.kt | 7 ++++-- .../main/java/org/prebid/mobile/AdUnit.java | 23 ++++++++----------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt index 2fc0c8c1f..2a1f517de 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayBanner320x50Activity.kt @@ -31,7 +31,7 @@ class GamOriginalApiDisplayBanner320x50Activity : BaseAdActivity() { companion object { const val AD_UNIT_ID = "/21808260008/prebid_demo_app_original_api_banner" - const val CONFIG_ID = "prebid-demo-banner-320-50" + const val CONFIG_ID = "prebid-ita-banner-320-50" const val WIDTH = 320 const val HEIGHT = 50 } @@ -72,8 +72,11 @@ class GamOriginalApiDisplayBanner320x50Activity : BaseAdActivity() { parameters.api = listOf(Signals.Api.MRAID_3, Signals.Api.OMID_1) adUnit?.bannerParameters = parameters + // Optional: the activation of the native impression tracker + adUnit?.activatePrebidImpressionTracker(adView) + adUnit?.setAutoRefreshInterval(refreshTimeSeconds) - adUnit?.fetchDemand(request, adView) { + adUnit?.fetchDemand(request) { adView.loadAd(request) } } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index a385c6beb..dfcd518ac 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -151,20 +151,6 @@ public void fetchDemand(@NonNull final OnCompleteListener2 listener) { }); } - /** - * Loads ad and applies keywords to the ad object. - * Fetch demand with the visibility tracking for the - * - * @param adObject AdMob's ({@code AdManagerAdRequest} or {@code AdManagerAdRequest.Builder}) - * or AppLovin's ({@code MaxNativeAdLoader}) ad object - * @param adView the ad view object (f.e. {@code AdManagerAdView}) - * @param listener callback when operation is completed (success or fail) - */ - public void fetchDemand(Object adObject, View adView, @NonNull OnCompleteListener listener) { - adViewReference = new WeakReference<>(adView); - fetchDemand(adObject, listener); - } - /** * Loads ad and applies keywords to the ad object. * @@ -261,6 +247,15 @@ public void fetchDemand(OnFetchDemandResult listener) { }); } + /** + * Applies the native visibility tracker for tracking `burl` url. + * + * @param adView the ad view object (f.e. {@code AdManagerAdView}) + */ + public void activatePrebidImpressionTracker(View adView) { + adViewReference = new WeakReference<>(adView); + } + // MARK: - adunit context data aka inventory data (imp[].ext.data) /** From 801b7df8fbb4143518b832c0e8bfa7a916e95b91 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 11 Feb 2025 10:02:28 +0100 Subject: [PATCH 11/16] feat: remove old activator --- .../src/main/java/org/prebid/mobile/InterstitialAdUnit.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java index 793491eda..a4f8e7cdf 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java @@ -18,7 +18,6 @@ import androidx.annotation.IntRange; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import org.prebid.mobile.api.data.AdFormat; import org.prebid.mobile.api.data.AdUnitFormat; @@ -70,10 +69,6 @@ public void setMinSizePercentage( configuration.setMinSizePercentage(new AdSize(width, height)); } - public void useInterstitialVisibilityTracker(boolean enable) { - this.useInterstitialVisibilityTracker = enable; - } - public void activatePrebidImpressionTracker(boolean activate) { this.activatePrebidImpressionTracker = activate; } From 2b8923e51859c4f58da498beef7cc1306c73bd7d Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 11 Feb 2025 14:55:13 +0100 Subject: [PATCH 12/16] fix: do not stop previous monitor after receiving a new auction response --- .../src/main/java/org/prebid/mobile/AdUnit.java | 7 ------- .../main/java/org/prebid/mobile/VisibilityMonitor.java | 10 ++++------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index dfcd518ac..cbf94a790 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -19,13 +19,10 @@ import static org.prebid.mobile.PrebidMobile.AUTO_REFRESH_DELAY_MAX; import static org.prebid.mobile.PrebidMobile.AUTO_REFRESH_DELAY_MIN; -import android.app.Activity; -import android.app.Application; import android.content.Context; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -159,8 +156,6 @@ public void fetchDemand(@NonNull final OnCompleteListener2 listener) { * @param listener callback when operation is completed (success or fail) */ public void fetchDemand(Object adObject, @NonNull OnCompleteListener listener) { - visibilityMonitor.stopTracking(); - if (TextUtils.isEmpty(PrebidMobile.getPrebidServerAccountId())) { LogUtil.error("Empty account id."); listener.onComplete(ResultCode.INVALID_ACCOUNT_ID); @@ -543,8 +538,6 @@ public AdUnitConfiguration getConfiguration() { } private void registerVisibilityTrackerIfNeeded(BidResponse response) { - visibilityMonitor.stopTracking(); - if (response == null || response.getWinningBid() == null || response.getWinningBid().getBurl() == null) { return; } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java index 75862e6dc..d11c61eb5 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/VisibilityMonitor.java @@ -3,7 +3,6 @@ import android.app.Application; import android.content.Context; import android.os.CountDownTimer; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; @@ -109,10 +108,9 @@ public void onTick(long millisUntilFinished) { destroy(); } - AdViewUtils.findCacheId( - webView, - attachVisibilityTrackerTask(new WeakReference<>(webView), this, responseCacheId, lastWebViewHash) - ); + + AdViewUtils.CacheIdResult onCacheIdFound = createCacheIdFoundTask(new WeakReference<>(webView), this, responseCacheId, lastWebViewHash); + AdViewUtils.findCacheId(webView, onCacheIdFound); } private void attachVisibilityTracker(WebView webView) { @@ -174,7 +172,7 @@ private static WebView findRecursively(ViewGroup root) { return null; } - private static AdViewUtils.CacheIdResult attachVisibilityTrackerTask(WeakReference webViewReference, VisibilityTimer visibilityTimer, String responseCacheId, int lastWebViewHash) { + private static AdViewUtils.CacheIdResult createCacheIdFoundTask(WeakReference webViewReference, VisibilityTimer visibilityTimer, String responseCacheId, int lastWebViewHash) { return cacheId -> { if (cacheId == null || cacheId.isEmpty()) { return; From 9201b9f50e30bace15766229103eae93a70cbe93 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Wed, 12 Feb 2025 11:52:46 +0100 Subject: [PATCH 13/16] feat: add support of PrebidAdUnit --- .../GamOriginalApiDisplayInterstitialActivity.kt | 3 +-- .../org/prebid/mobile/InterstitialAdUnit.java | 5 ++++- .../prebid/mobile/api/original/PrebidAdUnit.java | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt index 8f3ebec5b..bd4dff22b 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt @@ -21,7 +21,6 @@ import com.google.android.gms.ads.LoadAdError import com.google.android.gms.ads.admanager.AdManagerAdRequest import com.google.android.gms.ads.admanager.AdManagerInterstitialAd import com.google.android.gms.ads.admanager.AdManagerInterstitialAdLoadCallback -import org.prebid.mobile.AdUnit import org.prebid.mobile.InterstitialAdUnit import org.prebid.mobile.prebidkotlindemo.activities.BaseAdActivity @@ -46,7 +45,7 @@ class GamOriginalApiDisplayInterstitialActivity : BaseAdActivity() { adUnit = InterstitialAdUnit(CONFIG_ID, 80, 60) // Activate additional impression tracker (for burl) - adUnit?.activatePrebidImpressionTracker(true) + adUnit?.activateInterstitialPrebidImpressionTracker(true) // 2. Make a bid request to Prebid Server val request = AdManagerAdRequest.Builder().build() diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java index a4f8e7cdf..bf452873b 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java @@ -69,7 +69,10 @@ public void setMinSizePercentage( configuration.setMinSizePercentage(new AdSize(width, height)); } - public void activatePrebidImpressionTracker(boolean activate) { + /** + * Applies the interstitial native visibility tracker for tracking `burl` url. + */ + public void activateInterstitialPrebidImpressionTracker(boolean activate) { this.activatePrebidImpressionTracker = activate; } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/PrebidAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/PrebidAdUnit.java index e1b4a0703..ffac94123 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/PrebidAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/PrebidAdUnit.java @@ -3,6 +3,8 @@ import static org.prebid.mobile.PrebidMobile.AUTO_REFRESH_DELAY_MAX; import static org.prebid.mobile.PrebidMobile.AUTO_REFRESH_DELAY_MIN; +import android.view.View; + import androidx.annotation.IntRange; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -11,6 +13,8 @@ import org.prebid.mobile.ResultCode; import org.prebid.mobile.api.data.BidInfo; +import java.lang.ref.WeakReference; + /** * Universal ad unit for original API. It allows to make multi-format request. * Fetch demand result provides access to bid info data {@link BidInfo}. @@ -22,6 +26,8 @@ public class PrebidAdUnit { @Nullable private MultiformatAdUnitFacade adUnit; + protected WeakReference adViewReference = new WeakReference<>(null); + /** * Default constructor. */ @@ -68,6 +74,15 @@ public void setAutoRefreshInterval( } } + /** + * Applies the banner native visibility tracker for tracking `burl` url. + * + * @param adView the ad view object (f.e. {@code AdManagerAdView}) + */ + public void activatePrebidImpressionTracker(View adView) { + adViewReference = new WeakReference<>(adView); + } + /** * Resumes auto refresh interval after stopping. */ @@ -116,6 +131,7 @@ private void baseFetchDemand( } adUnit = new MultiformatAdUnitFacade(configId, request); + adUnit.activatePrebidImpressionTracker(adViewReference.get()); OnCompleteListenerImpl innerListener = new OnCompleteListenerImpl(adUnit, adObject, userListener); if (adObject != null) { From ac925425c05be4b2a35d4693e19dea51fba8f564 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Wed, 12 Feb 2025 12:47:17 +0100 Subject: [PATCH 14/16] feat: add interstitial impression tracker support for PrebidAdUnit --- .../mobile/api/original/MultiformatAdUnitFacade.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/MultiformatAdUnitFacade.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/MultiformatAdUnitFacade.java index adc4e039a..4b0776c86 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/MultiformatAdUnitFacade.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/MultiformatAdUnitFacade.java @@ -45,6 +45,13 @@ public MultiformatAdUnitFacade(@NotNull String configId, @NonNull PrebidRequest setConfigurationBasedOnRequest(request); } + /** + * Applies the interstitial native visibility tracker for tracking `burl` url. + */ + public void activateInterstitialPrebidImpressionTracker() { + this.activateInterstitialPrebidImpressionTracker = true; + } + @Override protected BidRequesterListener createBidListener(OnCompleteListener originalListener) { return new BidRequesterListener() { From 099f616b06fc05492a3b8f3106d00624a9e4a13a Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Wed, 12 Feb 2025 12:48:02 +0100 Subject: [PATCH 15/16] refactor: remove activation parameter as in iOS --- .../src/main/java/org/prebid/mobile/AdUnit.java | 4 ++-- .../java/org/prebid/mobile/InterstitialAdUnit.java | 4 ++-- .../org/prebid/mobile/api/original/PrebidAdUnit.java | 11 +++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java index cbf94a790..7dd76c566 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/AdUnit.java @@ -73,7 +73,7 @@ public abstract class AdUnit { protected WeakReference adViewReference = new WeakReference<>(null); protected boolean allowNullableAdObject = false; - protected boolean activatePrebidImpressionTracker = false; + protected boolean activateInterstitialPrebidImpressionTracker = false; public AdUnit(@NotNull String configId) { configuration.setConfigId(configId); @@ -557,7 +557,7 @@ private void registerVisibilityTrackerIfNeeded(BidResponse response) { boolean isBannerTracker = !(this instanceof InterstitialAdUnit); if (isBannerTracker) { bannerVisibilityTracker(burl, cacheId); - } else if (activatePrebidImpressionTracker) { + } else if (activateInterstitialPrebidImpressionTracker) { interstitialVisibilityTracker(burl, cacheId); } } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java index bf452873b..05a021460 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/InterstitialAdUnit.java @@ -72,8 +72,8 @@ public void setMinSizePercentage( /** * Applies the interstitial native visibility tracker for tracking `burl` url. */ - public void activateInterstitialPrebidImpressionTracker(boolean activate) { - this.activatePrebidImpressionTracker = activate; + public void activateInterstitialPrebidImpressionTracker() { + this.activateInterstitialPrebidImpressionTracker = true; } } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/PrebidAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/PrebidAdUnit.java index ffac94123..e6e20e2a5 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/PrebidAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/original/PrebidAdUnit.java @@ -26,6 +26,7 @@ public class PrebidAdUnit { @Nullable private MultiformatAdUnitFacade adUnit; + protected boolean activateInterstitialPrebidImpressionTracker = false; protected WeakReference adViewReference = new WeakReference<>(null); /** @@ -83,6 +84,13 @@ public void activatePrebidImpressionTracker(View adView) { adViewReference = new WeakReference<>(adView); } + /** + * Applies the interstitial native visibility tracker for tracking `burl` url. + */ + public void activateInterstitialPrebidImpressionTracker(boolean activate) { + this.activateInterstitialPrebidImpressionTracker = activate; + } + /** * Resumes auto refresh interval after stopping. */ @@ -132,6 +140,9 @@ private void baseFetchDemand( adUnit = new MultiformatAdUnitFacade(configId, request); adUnit.activatePrebidImpressionTracker(adViewReference.get()); + if (activateInterstitialPrebidImpressionTracker) { + adUnit.activateInterstitialPrebidImpressionTracker(); + } OnCompleteListenerImpl innerListener = new OnCompleteListenerImpl(adUnit, adObject, userListener); if (adObject != null) { From 5a5a3ebe5b53e80537bd1d9de664531684e386f1 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Wed, 12 Feb 2025 12:56:55 +0100 Subject: [PATCH 16/16] fix: after refactoring --- .../gam/original/GamOriginalApiDisplayInterstitialActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt index bd4dff22b..263270f06 100644 --- a/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt +++ b/Example/PrebidDemoKotlin/src/main/java/org/prebid/mobile/prebidkotlindemo/activities/ads/gam/original/GamOriginalApiDisplayInterstitialActivity.kt @@ -45,7 +45,7 @@ class GamOriginalApiDisplayInterstitialActivity : BaseAdActivity() { adUnit = InterstitialAdUnit(CONFIG_ID, 80, 60) // Activate additional impression tracker (for burl) - adUnit?.activateInterstitialPrebidImpressionTracker(true) + adUnit?.activateInterstitialPrebidImpressionTracker() // 2. Make a bid request to Prebid Server val request = AdManagerAdRequest.Builder().build()