From ed3faaac8be689141767e102e8a87636158d15d1 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Mon, 16 May 2022 09:21:05 +0300 Subject: [PATCH 1/4] feat: support win event in rendering API #443 --- .../mobile/admob/PrebidNativeAdapter.java | 2 + .../org/prebid/mobile/PrebidNativeAd.java | 27 +++++++- .../mobile/api/rendering/DisplayView.java | 5 ++ .../bidding/data/bid/BidResponse.java | 10 +++ .../rendering/bidding/data/bid/Prebid.java | 28 ++++++++ .../display/InterstitialController.java | 9 ++- .../bidding/events/EventsNotifier.java | 69 +++++++++++++++++++ .../rendering/networking/WinNotifier.java | 9 +++ .../prebid/managers/MaxNativeManager.java | 3 + 9 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/events/EventsNotifier.java diff --git a/PrebidMobile/PrebidMobile-admobAdapters/src/main/java/org/prebid/mobile/admob/PrebidNativeAdapter.java b/PrebidMobile/PrebidMobile-admobAdapters/src/main/java/org/prebid/mobile/admob/PrebidNativeAdapter.java index 9b8d0697c..3f71e17b2 100644 --- a/PrebidMobile/PrebidMobile-admobAdapters/src/main/java/org/prebid/mobile/admob/PrebidNativeAdapter.java +++ b/PrebidMobile/PrebidMobile-admobAdapters/src/main/java/org/prebid/mobile/admob/PrebidNativeAdapter.java @@ -20,6 +20,7 @@ import org.prebid.mobile.NativeAdUnit; import org.prebid.mobile.ParametersMatcher; import org.prebid.mobile.PrebidNativeAd; +import org.prebid.mobile.rendering.bidding.events.EventsNotifier; import java.io.InputStream; import java.net.HttpURLConnection; @@ -72,6 +73,7 @@ public void requestNativeAd( adMobListener.onAdFailedToLoad(new AdError(1004, error, "prebid")); return; } + EventsNotifier.notify(nativeAd.getWinEvent()); PrebidNativeAdMapper mapper = new PrebidNativeAdMapper(nativeAd, adMobListener); configureMapper(mapper, nativeAd, context); diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/PrebidNativeAd.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/PrebidNativeAd.java index 1dcffcbdf..575bd26fb 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/PrebidNativeAd.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/PrebidNativeAd.java @@ -26,6 +26,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.prebid.mobile.rendering.bidding.events.EventsNotifier; import org.prebid.mobile.rendering.utils.helpers.ExternalViewerUtils; import java.util.ArrayList; @@ -45,6 +46,8 @@ public class PrebidNativeAd { private View registeredView; private PrebidNativeAdEventListener listener; private ArrayList impressionTrackers; + private String winEvent; + private String impEvent; public static PrebidNativeAd create(String cacheId) { @@ -143,6 +146,7 @@ public void onCacheExpired() { } } } + parseEvents(details, ad); return ad; } catch (JSONException e) { e.printStackTrace(); @@ -151,6 +155,15 @@ public void onCacheExpired() { return null; } + private static void parseEvents( + JSONObject bidJson, + PrebidNativeAd ad + ) { + ad.winEvent = EventsNotifier.parseEvent("win", bidJson); + ad.impEvent = EventsNotifier.parseEvent("imp", bidJson); + } + + private PrebidNativeAd() { } @@ -376,7 +389,10 @@ private boolean handleClick(View v, PrebidNativeAdEventListener listener) { return false; } - private boolean openNativeIntent(String url, Context context) { + private boolean openNativeIntent( + String url, + Context context + ) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { @@ -386,4 +402,13 @@ private boolean openNativeIntent(String url, Context context) { return false; } } + + public String getWinEvent() { + return winEvent; + } + + public String getImpEvent() { + return impEvent; + } + } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/rendering/DisplayView.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/rendering/DisplayView.java index f22e78115..65c35f0f5 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/rendering/DisplayView.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/rendering/DisplayView.java @@ -25,6 +25,7 @@ import org.prebid.mobile.configuration.AdUnitConfiguration; import org.prebid.mobile.rendering.bidding.data.bid.BidResponse; import org.prebid.mobile.rendering.bidding.display.BidResponseCache; +import org.prebid.mobile.rendering.bidding.events.EventsNotifier; import org.prebid.mobile.rendering.bidding.listeners.DisplayViewListener; import org.prebid.mobile.rendering.models.AdDetails; import org.prebid.mobile.rendering.networking.WinNotifier; @@ -40,6 +41,8 @@ public class DisplayView extends FrameLayout { private final static String TAG = DisplayView.class.getSimpleName(); private static final String CONTENT_DESCRIPTION_AD_VIEW = "adView"; + private String impressionEventUrl; + private AdUnitConfiguration adUnitConfiguration; private DisplayViewListener displayViewListener; private InterstitialManager interstitialManager; @@ -152,6 +155,7 @@ public DisplayView( } else { displayHtmlAd(response); } + impressionEventUrl = response.getImpressionEventUrl(); } catch (AdException e) { notifyListenerError(e); } @@ -233,6 +237,7 @@ private void notifyListenerDisplayed() { if (displayViewListener != null) { displayViewListener.onAdDisplayed(); } + EventsNotifier.notify(impressionEventUrl); } private void notifyListenerLoaded() { diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/data/bid/BidResponse.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/data/bid/BidResponse.java index 58a28b37d..e008bcd4c 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/data/bid/BidResponse.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/data/bid/BidResponse.java @@ -252,4 +252,14 @@ public void setMobileSdkPassThrough(@Nullable MobileSdkPassThrough mobileSdkPass this.mobileSdkPassThrough = mobileSdkPassThrough; } + @Nullable + public String getImpressionEventUrl() { + Bid winningBid = getWinningBid(); + if (winningBid != null) { + Prebid prebid = winningBid.getPrebid(); + return prebid.getImpEventUrl(); + } + return null; + } + } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/data/bid/Prebid.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/data/bid/Prebid.java index fbe088ac4..01950c15a 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/data/bid/Prebid.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/data/bid/Prebid.java @@ -17,7 +17,10 @@ package org.prebid.mobile.rendering.bidding.data.bid; import android.text.TextUtils; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; import org.prebid.mobile.AdSize; import org.prebid.mobile.PrebidMobile; @@ -36,6 +39,8 @@ public class Prebid { private Cache cache; private HashMap targeting = new HashMap<>(); private String type; + private String winEventUrl; + private String impEventUrl; protected Prebid() { } @@ -62,10 +67,19 @@ public static Prebid fromJSONObject(JSONObject jsonObject) { } prebid.cache = Cache.fromJSONObject(jsonObject.optJSONObject("cache")); prebid.type = jsonObject.optString("type"); + parseEvents(prebid, jsonObject.optJSONObject("events")); toHashMap(prebid.targeting, jsonObject.optJSONObject("targeting")); return prebid; } + public String getWinEventUrl() { + return winEventUrl; + } + + public String getImpEventUrl() { + return impEventUrl; + } + public static JSONObject getJsonObjectForImp(AdUnitConfiguration adUnitConfiguration) { final JSONObject prebidObject = getPrebidObject(adUnitConfiguration.getConfigId()); @@ -124,6 +138,19 @@ public static JSONObject getJsonObjectForDeviceMinSizePerc(AdSize minSizePercent return prebid; } + + private static void parseEvents( + @NonNull Prebid prebid, + @Nullable JSONObject eventsJson + ) { + if (eventsJson == null) return; + + try { + prebid.winEventUrl = eventsJson.getString("win"); + prebid.impEventUrl = eventsJson.getString("imp"); + } catch (JSONException ignored) {} + } + private static JSONObject getPrebidObject(String configId) { JSONObject prebid = new JSONObject(); StoredRequest storedRequest = new StoredRequest(configId); @@ -173,4 +200,5 @@ private static void toHashMap(HashMap hashMap, JSONObject jsonOb hashMap.put(key, jsonObject.optString(key)); } } + } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/display/InterstitialController.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/display/InterstitialController.java index 50ea7ab3f..1679da30c 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/display/InterstitialController.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/display/InterstitialController.java @@ -23,6 +23,7 @@ import org.prebid.mobile.api.rendering.InterstitialView; import org.prebid.mobile.configuration.AdUnitConfiguration; import org.prebid.mobile.rendering.bidding.data.bid.BidResponse; +import org.prebid.mobile.rendering.bidding.events.EventsNotifier; import org.prebid.mobile.rendering.bidding.interfaces.InterstitialControllerListener; import org.prebid.mobile.rendering.bidding.interfaces.InterstitialViewListener; import org.prebid.mobile.rendering.models.AdDetails; @@ -33,6 +34,8 @@ public class InterstitialController { private static final String TAG = InterstitialController.class.getSimpleName(); + private String impressionEventUrl; + private final InterstitialView bidInterstitialView; private final InterstitialControllerListener listener; private AdFormat adUnitIdentifierType; @@ -40,8 +43,8 @@ public class InterstitialController { private final InterstitialViewListener interstitialViewListener = new InterstitialViewListener() { @Override public void onAdLoaded( - InterstitialView interstitialView, - AdDetails adDetails + InterstitialView interstitialView, + AdDetails adDetails ) { LogUtil.debug(TAG, "onAdLoaded"); if (listener != null) { @@ -66,6 +69,7 @@ public void onAdDisplayed(InterstitialView interstitialView) { if (listener != null) { listener.onInterstitialDisplayed(); } + EventsNotifier.notify(impressionEventUrl); } @Override @@ -106,6 +110,7 @@ public void loadAd(AdUnitConfiguration adUnitConfiguration, BidResponse bidRespo setRenderingControlSettings(adUnitConfiguration, bidResponse); WinNotifier winNotifier = new WinNotifier(); winNotifier.notifyWin(bidResponse, () -> { + impressionEventUrl = bidResponse.getImpressionEventUrl(); adUnitIdentifierType = bidResponse.isVideo() ? AdFormat.VAST : AdFormat.INTERSTITIAL; adUnitConfiguration.setAdFormat(adUnitIdentifierType); bidInterstitialView.loadAd(adUnitConfiguration, bidResponse); diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/events/EventsNotifier.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/events/EventsNotifier.java new file mode 100644 index 000000000..b630ceaa6 --- /dev/null +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/events/EventsNotifier.java @@ -0,0 +1,69 @@ +package org.prebid.mobile.rendering.bidding.events; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import org.json.JSONObject; +import org.prebid.mobile.LogUtil; +import org.prebid.mobile.rendering.bidding.data.bid.Bid; +import org.prebid.mobile.rendering.bidding.data.bid.BidResponse; +import org.prebid.mobile.rendering.bidding.data.bid.Prebid; +import org.prebid.mobile.rendering.networking.tracking.ServerConnection; + +/** + * Class for sending events from bids (seatbid.bid.ext.prebid.events.*) + */ +public class EventsNotifier { + + private static final String TAG = EventsNotifier.class.getSimpleName(); + + public static void notify(@Nullable String url) { + if (url != null) { + LogUtil.verbose(TAG, "Notify event: " + url); + ServerConnection.fireAndForget(url); + } + } + + /** + * Parses events in bid. + * + * @param bidJson - bid field from seatbid.bid + */ + @Nullable + public static String parseEvent( + @NonNull String eventKey, + @Nullable JSONObject bidJson + ) { + if (bidJson == null) return null; + + JSONObject extJson = bidJson.optJSONObject("ext"); + if (extJson != null) { + JSONObject prebidJson = extJson.optJSONObject("prebid"); + if (prebidJson != null) { + JSONObject eventsJson = prebidJson.optJSONObject("events"); + if (eventsJson != null) { + String result = eventsJson.optString(eventKey, ""); + if (!result.isEmpty()) { + return result; + } + } + } + } + + return null; + } + + + @Nullable + private static String getImpressionEventUrl(@Nullable BidResponse bidResponse) { + if (bidResponse == null) return null; + + Bid winningBid = bidResponse.getWinningBid(); + if (winningBid != null) { + Prebid prebid = winningBid.getPrebid(); + return prebid.getImpEventUrl(); + } + + return null; + } + +} diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/networking/WinNotifier.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/networking/WinNotifier.java index 0b437f9b7..b02a4ec70 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/networking/WinNotifier.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/networking/WinNotifier.java @@ -24,6 +24,7 @@ import org.prebid.mobile.LogUtil; import org.prebid.mobile.rendering.bidding.data.bid.Bid; import org.prebid.mobile.rendering.bidding.data.bid.BidResponse; +import org.prebid.mobile.rendering.bidding.data.bid.Prebid; import org.prebid.mobile.rendering.networking.tracking.ServerConnection; import java.util.Collections; @@ -92,10 +93,12 @@ public void notifyWin(BidResponse bidResponse, String cacheIdUrl = getCacheUrlFromBid(bid, KEY_CACHE_ID); String uuidUrl = getCacheUrlFromBid(bid, KEY_UUID); + String winUrl = getWinUrl(bid); urlQueue.add(cacheIdUrl); urlQueue.add(uuidUrl); urlQueue.add(bid.getNurl()); + urlQueue.add(winUrl); urlQueue.removeAll(Collections.singleton(null)); sendNextWinRequest(); @@ -175,8 +178,14 @@ private String getUrlTemplate() { } } + private String getWinUrl(@NonNull Bid bid) { + Prebid prebid = bid.getPrebid(); + return prebid.getWinEventUrl(); + } + @VisibleForTesting void enableTestFlag() { isUnderTest = true; } + } diff --git a/PrebidMobile/PrebidMobile-maxAdapters/src/main/java/com/applovin/mediation/adapters/prebid/managers/MaxNativeManager.java b/PrebidMobile/PrebidMobile-maxAdapters/src/main/java/com/applovin/mediation/adapters/prebid/managers/MaxNativeManager.java index c87e202df..6fbfbe9de 100644 --- a/PrebidMobile/PrebidMobile-maxAdapters/src/main/java/com/applovin/mediation/adapters/prebid/managers/MaxNativeManager.java +++ b/PrebidMobile/PrebidMobile-maxAdapters/src/main/java/com/applovin/mediation/adapters/prebid/managers/MaxNativeManager.java @@ -16,6 +16,7 @@ import com.applovin.mediation.adapters.prebid.PrebidMaxNativeAd; import com.applovin.mediation.nativeAds.MaxNativeAd; import org.prebid.mobile.PrebidNativeAd; +import org.prebid.mobile.rendering.bidding.events.EventsNotifier; import java.io.InputStream; import java.net.HttpURLConnection; @@ -41,6 +42,8 @@ public void loadAd( return; } + EventsNotifier.notify(prebidNativeAd.getWinEvent()); + MaxNativeAd maxNativeAd = createMaxNativeAd(prebidNativeAd, activity, maxListener); maxListener.onNativeAdLoaded(maxNativeAd, new Bundle()); } From e6012e81eddf7bdc680b91a91689c738b9b827c6 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Mon, 16 May 2022 16:51:49 +0300 Subject: [PATCH 2/4] feat: add native event notifications #443 Add examples. --- .../mobile/renderingtestapp/AdFragment.kt | 9 + .../utils/DemoItemProvider.kt | 182 +++++++++++++++++- .../src/main/res/values/strings.xml | 9 + .../org/prebid/mobile/PrebidNativeAd.java | 11 ++ .../rendering/utils/ntv/NativeAdProvider.java | 2 + 5 files changed, 203 insertions(+), 10 deletions(-) diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/AdFragment.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/AdFragment.kt index ab1bbff69..0e00ec594 100644 --- a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/AdFragment.kt +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/AdFragment.kt @@ -19,6 +19,7 @@ package org.prebid.mobile.renderingtestapp import android.app.Activity import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.Gravity import android.view.View import android.view.ViewGroup @@ -38,7 +39,11 @@ import org.prebid.mobile.renderingtestapp.utils.OpenRtbConfigs abstract class AdFragment : BaseFragment() { companion object { + private val TAG = AdFragment::class.simpleName + const val CONFIGURATOR_REQUEST_CODE = 0 + + const val ARGUMENT_ACCOUNT_ID = "ARGUMENT_ACCOUNT_ID" } var idlingResource = CountingIdlingResource(AdFragment::class.java.simpleName) @@ -64,6 +69,10 @@ abstract class AdFragment : BaseFragment() { val title = it.getString(getString(R.string.key_title), getString(R.string.segment_title_in_app)) setTitle(title) shouldSetNoBids() + it.getString(ARGUMENT_ACCOUNT_ID)?.let { accountId -> + Log.d(TAG, "Using custom account id: $accountId") + PrebidMobile.setPrebidServerAccountId(accountId) + } } if (ConfigurationViewSettings.isEnabled && configuratorMode() != null) { startAdConfigurator() diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/utils/DemoItemProvider.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/utils/DemoItemProvider.kt index 967bb9cec..16cccdeaa 100644 --- a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/utils/DemoItemProvider.kt +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/utils/DemoItemProvider.kt @@ -18,6 +18,7 @@ package org.prebid.mobile.renderingtestapp.utils import android.content.Context import android.os.Bundle +import org.prebid.mobile.renderingtestapp.AdFragment import org.prebid.mobile.renderingtestapp.R import org.prebid.mobile.renderingtestapp.data.DemoItem import org.prebid.mobile.renderingtestapp.data.Tag @@ -95,7 +96,6 @@ class DemoItemProvider private constructor() { val ppmInterstitialTagList = listOf(Tag.ALL, Tag.IN_APP, Tag.INTERSTITIAL, Tag.REMOTE) val ppmMraidTagList = listOf(Tag.ALL, Tag.IN_APP, Tag.MRAID, Tag.REMOTE) val ppmVideoTagList = listOf(Tag.ALL, Tag.IN_APP, Tag.VIDEO, Tag.REMOTE) - val ppmNativeTagList = listOf(Tag.ALL, Tag.IN_APP, Tag.NATIVE, Tag.REMOTE) // In-App Banner @@ -112,13 +112,40 @@ class DemoItemProvider private constructor() { getString(R.string.demo_bidding_in_app_banner_320_50_imp_prebid_random_bid), ppmBannerAction, ppmBannerTagList, - createBannerBundle(R.string.imp_prebid_id_banner_320x50, null, 320, 50, R.string.response_prebid_banner_320_50) + createBannerBundle( + R.string.imp_prebid_id_banner_320x50, + null, + 320, + 50, + R.string.response_prebid_banner_320_50 + ) ) ) demoList.add( DemoItem( - getString(R.string.demo_bidding_in_app_banner_320_50_no_bids), ppmBannerAction, - ppmBannerTagList, createBannerBundle(R.string.imp_prebid_id_no_bids, null, 320, 50, R.string.response_prebid_no_bids) + getString(R.string.demo_bidding_in_app_banner_320_50_no_bids), + ppmBannerAction, + ppmBannerTagList, + createBannerBundle(R.string.imp_prebid_id_no_bids, null, 320, 50, R.string.response_prebid_no_bids) + ) + ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_in_app_banner_320_50_events), + ppmBannerAction, + ppmBannerTagList, + createBannerBundle( + R.string.imp_prebid_id_banner_320x50, + null, + 320, + 50, + R.string.response_prebid_banner_320_50 + ).apply { + putString( + AdFragment.ARGUMENT_ACCOUNT_ID, + getString(R.string.prebid_account_id_prod_enabled_events) + ) + } ) ) demoList.add( @@ -126,7 +153,13 @@ class DemoItemProvider private constructor() { getString(R.string.demo_bidding_in_app_banner_300_250), ppmBannerAction, ppmBannerTagList, - createBannerBundle(R.string.imp_prebid_id_banner_300x250, null, 300, 250,R.string.response_prebid_banner_300_250) + createBannerBundle( + R.string.imp_prebid_id_banner_300x250, + null, + 300, + 250, + R.string.response_prebid_banner_300_250 + ) ) ) demoList.add( @@ -631,7 +664,10 @@ class DemoItemProvider private constructor() { getString(R.string.demo_bidding_in_app_native), R.id.action_header_bidding_to_in_app_native, ppmNativeTagList, - createBannerBundle(R.string.imp_prebid_id_native_styles,storedResponse = R.string.response_prebid_native_styles) + createBannerBundle( + R.string.imp_prebid_id_native_styles, + storedResponse = R.string.response_prebid_native_styles + ) ) ) demoList.add( @@ -647,7 +683,26 @@ class DemoItemProvider private constructor() { getString(R.string.demo_bidding_in_app_native_links), R.id.action_header_bidding_to_in_app_native_links, ppmNativeTagList, - createBannerBundle(R.string.imp_prebid_id_native_links,storedResponse = R.string.response_prebid_native_links) + createBannerBundle( + R.string.imp_prebid_id_native_links, + storedResponse = R.string.response_prebid_native_links + ) + ) + ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_in_app_native_events), + R.id.action_header_bidding_to_in_app_native, + ppmNativeTagList, + createBannerBundle( + R.string.imp_prebid_id_native_styles, + storedResponse = R.string.response_prebid_native_styles + ).apply { + putString( + AdFragment.ARGUMENT_ACCOUNT_ID, + getString(R.string.prebid_account_id_prod_enabled_events) + ) + } ) ) } @@ -701,10 +756,28 @@ class DemoItemProvider private constructor() { R.string.imp_prebid_id_banner_320x50, R.string.adunit_gam_banner_320_50_random, 320, - 50,R.string.response_prebid_banner_320_50 + 50, R.string.response_prebid_banner_320_50 ) ) ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_gam_banner_320_50_app_event_with_events_url), + gamBannerAction, + gamBannerTagList, + createBannerBundle( + R.string.imp_prebid_id_banner_320x50, + R.string.adunit_gam_banner_320_50_app_event, + 320, + 50, R.string.response_prebid_banner_320_50 + ).apply { + putString( + AdFragment.ARGUMENT_ACCOUNT_ID, + getString(R.string.prebid_account_id_prod_enabled_events) + ) + } + ) + ) demoList.add( DemoItem( getString(R.string.demo_bidding_gam_banner_300_250), @@ -714,7 +787,7 @@ class DemoItemProvider private constructor() { R.string.imp_prebid_id_banner_300x250, R.string.adunit_gam_banner_300_250, 300, - 250,R.string.response_prebid_banner_300_250 + 250, R.string.response_prebid_banner_300_250 ) ) ) @@ -1027,9 +1100,28 @@ class DemoItemProvider private constructor() { ) ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_gam_native_custom_templates_events), + R.id.action_header_bidding_to_gam_native, + gamNativeTagList, + createBannerBundle( + R.string.imp_prebid_id_native_styles, + R.string.adunit_gam_native_custom_template, + storedResponse = R.string.response_prebid_native_styles + ).apply { + putString(GamNativeFragment.ARG_CUSTOM_FORMAT_ID, "11934135") + putString( + AdFragment.ARGUMENT_ACCOUNT_ID, + getString(R.string.prebid_account_id_prod_enabled_events) + ) + } + ) + ) + gamNativeBundle = createBannerBundle( R.string.imp_prebid_id_no_bids, - R.string.adunit_gam_native_custom_template,storedResponse = R.string.response_prebid_no_bids + R.string.adunit_gam_native_custom_template, storedResponse = R.string.response_prebid_no_bids ) gamNativeBundle.putString(GamNativeFragment.ARG_CUSTOM_FORMAT_ID, "11982639") demoList.add( @@ -1147,6 +1239,24 @@ class DemoItemProvider private constructor() { ) ) ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_admob_banner_320_50_adapter_with_events), + adMobBannerAction, + adMobBannerTagList, + createBannerBundle( + R.string.imp_prebid_id_banner_320x50_high_price, + R.string.admob_banner_bidding_ad_unit_id_adapter, + 320, 50, + R.string.response_prebid_banner_320_50 + ).apply { + putString( + AdFragment.ARGUMENT_ACCOUNT_ID, + getString(R.string.prebid_account_id_prod_enabled_events) + ) + } + ) + ) demoList.add( DemoItem( getString(R.string.demo_bidding_admob_banner_300_250_adapter), @@ -1350,6 +1460,23 @@ class DemoItemProvider private constructor() { ) ) ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_admob_native_adapter_events), + adMobNativeAction, + adMobNativeTagList, + createBannerBundle( + R.string.imp_prebid_id_native_styles, + R.string.admob_native_bidding_ad_unit_id_adapter, + storedResponse = R.string.response_prebid_native_styles + ).apply { + putString( + AdFragment.ARGUMENT_ACCOUNT_ID, + getString(R.string.prebid_account_id_prod_enabled_events) + ) + } + ) + ) } private fun addApplovinMaxPbsExamples() { @@ -1397,6 +1524,24 @@ class DemoItemProvider private constructor() { ) ) ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_max_banner_320_50_adapter_with_events), + maxBannerAction, + maxBannerTagList, + createBannerBundle( + R.string.imp_prebid_id_banner_320x50, + R.string.max_banner_ad_unit_id, + 320, 50, + R.string.response_prebid_banner_320_50 + ).apply { + putString( + AdFragment.ARGUMENT_ACCOUNT_ID, + getString(R.string.prebid_account_id_prod_enabled_events) + ) + } + ) + ) demoList.add( DemoItem( getString(R.string.demo_bidding_max_banner_300_250_adapter), @@ -1621,6 +1766,23 @@ class DemoItemProvider private constructor() { ) ) ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_max_native_adapter_events), + maxNativeAction, + maxNativeTagList, + createBannerBundle( + R.string.imp_prebid_id_native_styles, + R.string.max_native_ad_unit_id, + storedResponse = R.string.response_prebid_native_styles + ).apply { + putString( + AdFragment.ARGUMENT_ACCOUNT_ID, + getString(R.string.prebid_account_id_prod_enabled_events) + ) + } + ) + ) } private fun createBannerBundle( diff --git a/Example/PrebidInternalTestApp/src/main/res/values/strings.xml b/Example/PrebidInternalTestApp/src/main/res/values/strings.xml index b379360d2..d854fc336 100755 --- a/Example/PrebidInternalTestApp/src/main/res/values/strings.xml +++ b/Example/PrebidInternalTestApp/src/main/res/values/strings.xml @@ -79,6 +79,7 @@ Banner 320x50 (In-App) + Banner 320x50 Events (In-App) Banner 320x50 [noBids] (In-App) Banner 320x50 [Bid - RANDOM noBids, Ad - RESPECTIVE] Banner 300x250 (In-App) @@ -129,12 +130,14 @@ Banner Native Styles No Assets (In-App) Banner Native Styles No Creative (In-App) Native Ad (In-App) + Native Ad Events (In-App) Native Ad Feed (In-App) Native Ad Links (In-App) Native Ad Video (In-App) Banner 320x50 (GAM) [OK, AppEvent] + Banner 320x50 Events (GAM) [OK, AppEvent] Banner 320x50 (GAM) [OK, GAM Ad] Banner 320x50 (GAM) [noBids, GAM Ad] Banner 320x50 (GAM) [OK, Random] @@ -167,6 +170,7 @@ Banner Native Styles (GAM) [Fluid] Banner Native Styles No Assets (GAM) [MRect] Native Ad Custom Templates (GAM) [OK, NativeAd] + Native Ad Custom Templates Events (GAM) [OK, NativeAd] Native Ad (GAM) [noBids, GADNativeCustomTemplateAd] Native Ad Unified Ad (GAM) [OK, NativeAd] Native Ad (GAM) [noBids, GADUnifiedNativeAd] @@ -179,6 +183,7 @@ Banner 320x50 (AdMob) [OK, OXB Adapter] + Banner 320x50 Events (AdMob) [OK, OXB Adapter] Banner 320x50 (AdMob) [OK, Random] Banner 320x50 (AdMob) [noBids, AdMob ad] Banner 320x50 (AdMob) [Random, Respectively] @@ -200,10 +205,12 @@ Video Rewarded 320x480 (AdMob) [OK, Random] Native Ad (AdMob) [OK, OXB Adapter] + Native Ad Events (AdMob) [OK, OXB Adapter] Native Ad (AdMob) [noBids, AdMob ad] Banner 320x50 (MAX) [OK, Adapter] + Banner 320x50 Events (MAX) [OK, Adapter] Banner 320x50 (MAX) [noBids, MAX ad] Banner 320x50 (MAX) [Random, Respectively] Banner 300x250 (MAX) [OK, Adapter] @@ -224,6 +231,7 @@ Video Rewarded 320x480 no EndCard (MAX) [OK, Adapter] Native Ad (MAX) [OK, Adapter] + Native Ad Events (MAX) [OK, Adapter] Native Ad (MAX) [noBids, MAX ad] @@ -271,6 +279,7 @@ 0689a263-318d-448b-a3d4-b02e8a709d9d 1768035c-74d3-4786-b056-13bd41f34bde + prebid-stored-request-enabled-events 50699c03-0910-477c-b4a4-911dbe2b9d42 758bef6c-a811-497e-8234-9a583daf92e0 diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/PrebidNativeAd.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/PrebidNativeAd.java index 575bd26fb..b0df0f8d4 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/PrebidNativeAd.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/PrebidNativeAd.java @@ -36,6 +36,8 @@ public class PrebidNativeAd { private static final String TAG = "PrebidNativeAd"; + private boolean impressionIsNotNotified = true; + private final ArrayList titles = new ArrayList<>(); private final ArrayList images = new ArrayList<>(); private final ArrayList dataList = new ArrayList<>(); @@ -296,6 +298,7 @@ public void onImpressionTrackerFired() { if (listener != null) { listener.onAdImpression(); } + notifyImpressionEvent(); } }); impressionTrackers.add(impressionTracker); @@ -339,6 +342,7 @@ public void onImpressionTrackerFired() { if (listener != null) { listener.onAdImpression(); } + notifyImpressionEvent(); } }); impressionTrackers.add(impressionTracker); @@ -411,4 +415,11 @@ public String getImpEvent() { return impEvent; } + private void notifyImpressionEvent() { + if (impressionIsNotNotified) { + impressionIsNotNotified = false; + EventsNotifier.notify(impEvent); + } + } + } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/ntv/NativeAdProvider.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/ntv/NativeAdProvider.java index 58e38acbf..2397c42bf 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/ntv/NativeAdProvider.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/ntv/NativeAdProvider.java @@ -6,6 +6,7 @@ import org.prebid.mobile.LogUtil; import org.prebid.mobile.NativeAdUnit; import org.prebid.mobile.PrebidNativeAd; +import org.prebid.mobile.rendering.bidding.events.EventsNotifier; public class NativeAdProvider { @@ -25,6 +26,7 @@ public static PrebidNativeAd getNativeAd(@NonNull Bundle extras) { LogUtil.error(TAG, "PrebidNativeAd is null"); return null; } + EventsNotifier.notify(nativeAd.getWinEvent()); return nativeAd; } From 98328899c73d08de44cf8a852d66238727b9bdad Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Mon, 16 May 2022 17:07:03 +0300 Subject: [PATCH 3/4] fix: fix null pointer #443 --- .../org/prebid/mobile/rendering/networking/WinNotifier.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/networking/WinNotifier.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/networking/WinNotifier.java index b02a4ec70..869145735 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/networking/WinNotifier.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/networking/WinNotifier.java @@ -180,7 +180,10 @@ private String getUrlTemplate() { private String getWinUrl(@NonNull Bid bid) { Prebid prebid = bid.getPrebid(); - return prebid.getWinEventUrl(); + if (prebid != null) { + return prebid.getWinEventUrl(); + } + return null; } @VisibleForTesting From 65f2aed64bbcaf957bcbdc8e0819f4c4c032c477 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 17 May 2022 19:40:22 +0300 Subject: [PATCH 4/4] feat: request impression urls when Open measurement impression notified #443 --- .../mobile/api/rendering/DisplayView.java | 3 +-- .../configuration/AdUnitConfiguration.java | 13 +++++++++++++ .../display/InterstitialController.java | 3 +-- .../rendering/loading/CreativeFactory.java | 19 +++++++++++++------ .../rendering/models/CreativeModel.java | 4 ++++ 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/rendering/DisplayView.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/rendering/DisplayView.java index 65c35f0f5..a29b732b3 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/rendering/DisplayView.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/api/rendering/DisplayView.java @@ -25,7 +25,6 @@ import org.prebid.mobile.configuration.AdUnitConfiguration; import org.prebid.mobile.rendering.bidding.data.bid.BidResponse; import org.prebid.mobile.rendering.bidding.display.BidResponseCache; -import org.prebid.mobile.rendering.bidding.events.EventsNotifier; import org.prebid.mobile.rendering.bidding.listeners.DisplayViewListener; import org.prebid.mobile.rendering.models.AdDetails; import org.prebid.mobile.rendering.networking.WinNotifier; @@ -150,6 +149,7 @@ public DisplayView( WinNotifier winNotifier = new WinNotifier(); winNotifier.notifyWin(response, () -> { try { + adUnitConfiguration.modifyUsingBidResponse(response); if (response.isVideo()) { displayVideoAd(response); } else { @@ -237,7 +237,6 @@ private void notifyListenerDisplayed() { if (displayViewListener != null) { displayViewListener.onAdDisplayed(); } - EventsNotifier.notify(impressionEventUrl); } private void notifyListenerLoaded() { diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/configuration/AdUnitConfiguration.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/configuration/AdUnitConfiguration.java index 11a0e999c..fb5aa82a7 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/configuration/AdUnitConfiguration.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/configuration/AdUnitConfiguration.java @@ -7,6 +7,7 @@ import org.prebid.mobile.api.data.AdFormat; import org.prebid.mobile.api.data.AdUnitFormat; import org.prebid.mobile.api.data.Position; +import org.prebid.mobile.rendering.bidding.data.bid.BidResponse; import org.prebid.mobile.rendering.interstitial.InterstitialSizes; import org.prebid.mobile.rendering.models.AdPosition; import org.prebid.mobile.rendering.models.PlacementType; @@ -40,6 +41,7 @@ public class AdUnitConfiguration { private String configId; private String pbAdSlot; private String interstitialSize; + private String impressionUrl; private Position closeButtonPosition = Position.TOP_RIGHT; private Position skipButtonPosition = Position.TOP_RIGHT; @@ -58,6 +60,12 @@ public class AdUnitConfiguration { private final Set contextKeywordsSet = new HashSet<>(); + public void modifyUsingBidResponse(@Nullable BidResponse bidResponse) { + if (bidResponse != null) { + impressionUrl = bidResponse.getImpressionEventUrl(); + } + } + public void setConfigId(String configId) { this.configId = configId; } @@ -438,6 +446,11 @@ public void setIsOriginalAdUnit(boolean originalAdUnit) { isOriginalAdUnit = originalAdUnit; } + public String getImpressionUrl() { + return impressionUrl; + } + + @Override public boolean equals(Object o) { if (this == o) { diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/display/InterstitialController.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/display/InterstitialController.java index 1679da30c..e0b238325 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/display/InterstitialController.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/display/InterstitialController.java @@ -23,7 +23,6 @@ import org.prebid.mobile.api.rendering.InterstitialView; import org.prebid.mobile.configuration.AdUnitConfiguration; import org.prebid.mobile.rendering.bidding.data.bid.BidResponse; -import org.prebid.mobile.rendering.bidding.events.EventsNotifier; import org.prebid.mobile.rendering.bidding.interfaces.InterstitialControllerListener; import org.prebid.mobile.rendering.bidding.interfaces.InterstitialViewListener; import org.prebid.mobile.rendering.models.AdDetails; @@ -69,7 +68,6 @@ public void onAdDisplayed(InterstitialView interstitialView) { if (listener != null) { listener.onInterstitialDisplayed(); } - EventsNotifier.notify(impressionEventUrl); } @Override @@ -107,6 +105,7 @@ public InterstitialController(Context context, InterstitialControllerListener li } public void loadAd(AdUnitConfiguration adUnitConfiguration, BidResponse bidResponse) { + adUnitConfiguration.modifyUsingBidResponse(bidResponse); setRenderingControlSettings(adUnitConfiguration, bidResponse); WinNotifier winNotifier = new WinNotifier(); winNotifier.notifyWin(bidResponse, () -> { diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/loading/CreativeFactory.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/loading/CreativeFactory.java index c1788bdd1..401f41e3b 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/loading/CreativeFactory.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/loading/CreativeFactory.java @@ -150,8 +150,8 @@ private void attemptVastCreative() { String mediaUrl = videoCreativeModel.getMediaUrl(); if (Utils.isBlank(mediaUrl) || mediaUrl.equals("invalid media file")) { listener.onFailure(new AdException( - AdException.INTERNAL_ERROR, - VASTErrorCodes.NO_SUPPORTED_MEDIA_ERROR.toString() + AdException.INTERNAL_ERROR, + VASTErrorCodes.NO_SUPPORTED_MEDIA_ERROR.toString() )); return; } @@ -160,14 +160,21 @@ private void attemptVastCreative() { for (VideoAdEvent.Event videoEvent : VideoAdEvent.Event.values()) { videoCreativeModel.registerVideoEvent(videoEvent, videoCreativeModel.getVideoEventUrls().get(videoEvent)); } + ArrayList impressions = new ArrayList<>(1); + impressions.add(creativeModel.getImpressionUrl()); + videoCreativeModel.registerTrackingEvent( + TrackingEvent.Events.IMPRESSION, + impressions + ); VideoCreative newCreative; try { if (creativeModel.getAdConfiguration().isRewarded()) { - newCreative = new RewardedVideoCreative(contextReference.get(), - videoCreativeModel, - omAdSessionManager, - interstitialManager + newCreative = new RewardedVideoCreative( + contextReference.get(), + videoCreativeModel, + omAdSessionManager, + interstitialManager ); } else { newCreative = new VideoCreative(contextReference.get(), diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/CreativeModel.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/CreativeModel.java index ddef85daf..30f98e18d 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/CreativeModel.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/CreativeModel.java @@ -90,6 +90,10 @@ public CreativeModel( this.trackingManager = trackingManager; this.adConfiguration = adConfiguration; this.omEventTracker = omEventTracker; + + if (adConfiguration != null) { + setImpressionUrl(adConfiguration.getImpressionUrl()); + } } //tracking firing here from Model always