From 9d017064263b6283c7badf9462bd727f8422fcea Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 5 Apr 2022 10:44:30 +0300 Subject: [PATCH 1/5] feat(controls): add close button area property #388 --- .../parallel/BaseInterstitialAdUnit.java | 9 +++ .../rendering/interstitial/AdBaseDialog.java | 3 +- .../InterstitialLayoutConfigurator.java | 1 + ...InterstitialDisplayPropertiesInternal.java | 1 + .../mobile/rendering/utils/helpers/Utils.java | 72 ++++++++++++++++++- .../configuration/AdUnitConfiguration.java | 10 +++ .../src/main/res/layout/lyt_close.xml | 14 ++-- 7 files changed, 99 insertions(+), 11 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/parallel/BaseInterstitialAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/parallel/BaseInterstitialAdUnit.java index 1a2ec62e5..b1d58960d 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/parallel/BaseInterstitialAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/parallel/BaseInterstitialAdUnit.java @@ -17,6 +17,7 @@ package org.prebid.mobile.rendering.bidding.parallel; import android.content.Context; +import androidx.annotation.FloatRange; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.prebid.mobile.ContentObject; @@ -182,6 +183,14 @@ public void setMaxVideoDuration(int seconds) { adUnitConfig.setMaxVideoDuration(seconds); } + /** + * Sets close button percentage size in range from 0.05 to 1. + * If value less than 0.05, size will be default. + */ + public void setCloseButtonArea(@FloatRange(from = 0, to = 1.0) double closeButtonArea) { + adUnitConfig.setCloseButtonArea(closeButtonArea); + } + /** * Cleans up resources when destroyed. */ diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java index 52ba01358..110f55597 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java @@ -337,7 +337,8 @@ protected void addCloseView() { return; } - mCloseView = Utils.createCloseView(mContextReference.get()); + InterstitialDisplayPropertiesInternal properties = mInterstitialManager.getInterstitialDisplayProperties(); + mCloseView = Utils.createCloseView(mContextReference.get(), properties.closeButtonArea); if (mCloseView == null) { LogUtil.error(TAG, "Unable to add close button. Close view is null"); diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/InterstitialLayoutConfigurator.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/InterstitialLayoutConfigurator.java index 1a52a1377..c289e7ace 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/InterstitialLayoutConfigurator.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/InterstitialLayoutConfigurator.java @@ -38,6 +38,7 @@ public static void configureDisplayProperties(AdUnitConfiguration adConfiguratio displayProperties.isRotationEnabled = true; } + displayProperties.closeButtonArea = adConfiguration.getCloseButtonArea(); displayProperties.isSoundButtonVisible = adConfiguration.isSoundButtonVisible(); displayProperties.isMuted = adConfiguration.isMuted(); } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/InterstitialDisplayPropertiesInternal.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/InterstitialDisplayPropertiesInternal.java index 8216a7b2d..18a46004b 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/InterstitialDisplayPropertiesInternal.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/InterstitialDisplayPropertiesInternal.java @@ -22,6 +22,7 @@ public class InterstitialDisplayPropertiesInternal extends InterstitialDisplayPr public int expandWidth; public int expandHeight; + public double closeButtonArea; public int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; public boolean isSoundButtonVisible = false; public boolean isMuted = false; diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java index 61725c053..2c724e045 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java @@ -16,6 +16,7 @@ package org.prebid.mobile.rendering.utils.helpers; +import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -30,6 +31,7 @@ import android.widget.FrameLayout; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import org.json.JSONArray; import org.json.JSONException; @@ -429,8 +431,42 @@ public static Map getQueryMap(String query) { return map; } + private static final int MIN_BUTTON_SIZE_DP = 30; + public static View createCloseView(Context context) { - return createView(context, R.layout.lyt_close, Gravity.END | Gravity.TOP); + return createCloseView(context, null); + } + + public static View createCloseView( + Context context, + @Nullable Double closeButtonArea + ) { + if (context == null) { + LogUtil.error(TAG, "Unable to create close view. Context is null"); + return null; + } + + FrameLayout.LayoutParams params; + View closeView = LayoutInflater.from(context).inflate(R.layout.lyt_close, null); + if (closeButtonArea == null || closeButtonArea < 0.05 || closeButtonArea > 1) { + params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ); + } else { + int screenSize = getSmallestScreenSideSize(context); + int buttonSize = (int) (screenSize * closeButtonArea); + if (convertPxToDp(buttonSize, context) < MIN_BUTTON_SIZE_DP) { + buttonSize = convertDpToPx(MIN_BUTTON_SIZE_DP, context); + } + int padding = (int) (buttonSize * 0.2); + closeView.setPadding(padding, padding, padding, padding); + params = new FrameLayout.LayoutParams(buttonSize, buttonSize); + } + + params.gravity = Gravity.END | Gravity.TOP; + closeView.setLayoutParams(params); + return closeView; } public static View createSoundView(Context context) { @@ -457,13 +493,45 @@ private static View createView( return view; } + private static int getSmallestScreenSideSize(Context context) { + try { + DisplayMetrics displayMetrics = new DisplayMetrics(); + ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + int result = Math.min(displayMetrics.widthPixels, displayMetrics.heightPixels); + if (result > 0) { + return result; + } + } catch (Exception exception) {} + DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics(); + return Math.min(displayMetrics.heightPixels, displayMetrics.widthPixels); + } + + public static int convertPxToDp( + int px, + Context context + ) { + return (int) (px / ((float) context.getResources() + .getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT)); + } + + public static int convertDpToPx( + int dp, + Context context + ) { + return (int) (dp * ((float) context.getResources() + .getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT)); + } + public static View createWatchAgainView(Context context) { if (context == null) { LogUtil.error(TAG, "Unable to create watch again view. Context is null"); return null; } View watchAgainView = LayoutInflater.from(context).inflate(R.layout.lyt_watch_again, null); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ); params.gravity = Gravity.CENTER; watchAgainView.setLayoutParams(params); return watchAgainView; diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/AdUnitConfiguration.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/AdUnitConfiguration.java index 05f5dcb81..1b0488c99 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/AdUnitConfiguration.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/AdUnitConfiguration.java @@ -1,5 +1,6 @@ package org.prebid.mobile.units.configuration; +import androidx.annotation.FloatRange; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.prebid.mobile.*; @@ -27,6 +28,7 @@ public class AdUnitConfiguration { private int autoRefreshDelayInMillis = 0; private final int broadcastId = Utils.generateRandomInt(); private float videoInitialVolume = ExoPlayerView.DEFAULT_INITIAL_VIDEO_VOLUME; + private double closeButtonArea = 0; private int maxVideoDuration = 3600; @@ -295,6 +297,14 @@ public boolean isRewarded() { return isRewarded; } + public void setCloseButtonArea(@FloatRange(from = 0, to = 1.0) double closeButtonArea) { + this.closeButtonArea = closeButtonArea; + } + + public double getCloseButtonArea() { + return closeButtonArea; + } + public void setInterstitialSize(@Nullable InterstitialSizes.InterstitialSize size) { if (size != null) { interstitialSize = size.getSize(); diff --git a/PrebidMobile/PrebidMobile-core/src/main/res/layout/lyt_close.xml b/PrebidMobile/PrebidMobile-core/src/main/res/layout/lyt_close.xml index b486f7ba7..a9d639384 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/res/layout/lyt_close.xml +++ b/PrebidMobile/PrebidMobile-core/src/main/res/layout/lyt_close.xml @@ -1,5 +1,4 @@ - - - \ No newline at end of file + android:layout_width="70dp" + android:layout_height="70dp" + android:padding="15dp" + android:src="@drawable/prebid_ic_close_interstitial" /> \ No newline at end of file From a70ebfd81d598e82888f6d13b726d3e5b5d29d11 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 5 Apr 2022 11:36:55 +0300 Subject: [PATCH 2/5] feat(controls): add unit tests #388 --- .../mobile/rendering/utils/helpers/Utils.java | 5 +- .../rendering/utils/helpers/UtilsTest.java | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java index 2c724e045..0ff6b9f88 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java @@ -449,9 +449,8 @@ public static View createCloseView( FrameLayout.LayoutParams params; View closeView = LayoutInflater.from(context).inflate(R.layout.lyt_close, null); if (closeButtonArea == null || closeButtonArea < 0.05 || closeButtonArea > 1) { - params = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT + params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT ); } else { int screenSize = getSmallestScreenSideSize(context); diff --git a/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/utils/helpers/UtilsTest.java b/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/utils/helpers/UtilsTest.java index 0189a409a..0f0c5510e 100644 --- a/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/utils/helpers/UtilsTest.java +++ b/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/utils/helpers/UtilsTest.java @@ -16,12 +16,16 @@ package org.prebid.mobile.rendering.utils.helpers; +import android.app.Activity; import android.content.Context; import android.graphics.Point; import android.os.Build; import android.util.DisplayMetrics; import android.view.Display; +import android.view.Gravity; +import android.view.View; import android.view.WindowManager; +import android.widget.FrameLayout; import androidx.test.filters.Suppress; import junit.framework.TestCase; import org.json.JSONArray; @@ -35,8 +39,10 @@ import org.prebid.mobile.PrebidMobile; import org.prebid.mobile.rendering.networking.BaseNetworkTask; import org.prebid.mobile.test.utils.ResourceUtils; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import java.io.IOException; import java.lang.reflect.Field; @@ -51,6 +57,7 @@ import static org.mockito.Mockito.*; @RunWith(RobolectricTestRunner.class) +@Config(sdk = 19, qualifiers = "w1920dp-h1080dp") public class UtilsTest extends TestCase { @Test @@ -388,4 +395,54 @@ public void clampAutoRefresh_UserValueInRange_ReturnUserValue() { assertEquals(refreshDelaySec * 1000, clampAutoRefresh); } + + @Test + public void createCloseView_UseConstructorOnlyWithContext_CreateViewWithDefaultSize() { + Activity activity = Robolectric.buildActivity(Activity.class).get(); + + View closeView = Utils.createCloseView(activity); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); + + assertEquals(Gravity.END | Gravity.TOP, params.gravity); + assertEquals(FrameLayout.LayoutParams.WRAP_CONTENT, params.width); + assertEquals(FrameLayout.LayoutParams.WRAP_CONTENT, params.height); + } + + @Test + public void createCloseView_UseNullCloseButtonArea_CreateViewWithDefaultSize() { + Activity activity = Robolectric.buildActivity(Activity.class).get(); + + View closeView = Utils.createCloseView(activity, null); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); + + assertEquals(Gravity.END | Gravity.TOP, params.gravity); + assertEquals(FrameLayout.LayoutParams.WRAP_CONTENT, params.width); + assertEquals(FrameLayout.LayoutParams.WRAP_CONTENT, params.height); + } + + @Test + public void createCloseView_UseCloseButtonAreaOutOfRange_CreateViewWithDefaultSize() { + Activity activity = Robolectric.buildActivity(Activity.class).get(); + + View closeView = Utils.createCloseView(activity, 0.0); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); + + assertEquals(Gravity.END | Gravity.TOP, params.gravity); + assertEquals(FrameLayout.LayoutParams.WRAP_CONTENT, params.width); + assertEquals(FrameLayout.LayoutParams.WRAP_CONTENT, params.height); + } + + @Test + public void createCloseView_UseCustomCloseButtonArea_CreateViewWithCalculatedSize() { + Activity activity = Robolectric.buildActivity(Activity.class).get(); + + View closeView = Utils.createCloseView(activity, 0.2); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); + + assertEquals(Gravity.END | Gravity.TOP, params.gravity); + assertEquals(216, params.width); + assertEquals(216, params.height); + assertEquals(43, closeView.getPaddingTop()); + } + } From fdfe4f94089df9170fa96d746ba013c2045b6095 Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 5 Apr 2022 11:55:11 +0300 Subject: [PATCH 3/5] feat(controls): add internal example #388 --- .../PpmInterstitialCloseButtonAreaFragment.kt | 26 +++++++++++++++++++ .../utils/DemoItemProvider.kt | 16 ++++++++++++ .../res/navigation/bidding_navigation.xml | 14 ++++++++++ .../src/main/res/values/strings.xml | 1 + 4 files changed, 57 insertions(+) create mode 100644 Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/ppm/PpmInterstitialCloseButtonAreaFragment.kt diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/ppm/PpmInterstitialCloseButtonAreaFragment.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/ppm/PpmInterstitialCloseButtonAreaFragment.kt new file mode 100644 index 000000000..e01629897 --- /dev/null +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/ppm/PpmInterstitialCloseButtonAreaFragment.kt @@ -0,0 +1,26 @@ +package org.prebid.mobile.renderingtestapp.plugplay.bidding.ppm + +import org.prebid.mobile.rendering.bidding.enums.AdUnitFormat +import org.prebid.mobile.rendering.bidding.parallel.InterstitialAdUnit +import org.prebid.mobile.renderingtestapp.plugplay.bidding.base.BaseBidInterstitialFragment +import java.util.* + +class PpmInterstitialCloseButtonAreaFragment : BaseBidInterstitialFragment() { + + override fun initInterstitialAd( + adUnitFormat: AdUnitFormat, + adUnitId: String?, + configId: String?, + width: Int, + height: Int + ) { + interstitialAdUnit = if (adUnitFormat == AdUnitFormat.VIDEO) { + InterstitialAdUnit(requireContext(), configId, EnumSet.of(adUnitFormat)) + } else { + InterstitialAdUnit(requireContext(), configId) + } + interstitialAdUnit?.setInterstitialAdUnitListener(this) + interstitialAdUnit?.setCloseButtonArea(0.40) + } + +} \ No newline at end of file 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 558fcffde..72f34f4c4 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 @@ -35,6 +35,8 @@ class DemoItemProvider private constructor() { private const val ppmBannerAction = R.id.action_header_bidding_to_in_app_banner private const val ppmInterstitialAction = R.id.action_header_bidding_to_in_app_interstitial + private const val ppmInterstitialCloseButtonAreaAction = + R.id.action_header_bidding_to_in_app_interstitial_close_button_area private const val ppmInterstitialSoundButtonAction = R.id.action_header_bidding_to_in_app_interstitial_sound_button private const val ppmRewardedAction = R.id.action_header_bidding_to_in_app_video_rewarded @@ -425,6 +427,20 @@ class DemoItemProvider private constructor() { ) ) ) + demoList.add( + DemoItem( + getString(R.string.demo_bidding_in_app_interstitial_video_320_480_end_card_close_button_area), + ppmInterstitialCloseButtonAreaAction, + ppmVideoTagList, + createBannerBundle( + R.string.imp_prebid_id_video_interstitial_320_480_with_end_card, + null, + MIN_WIDTH_PERC, + MIN_HEIGHT_PERC, + R.string.response_prebid_video_interstitial_320_480_with_end_card + ) + ) + ) demoList.add( DemoItem( getString(R.string.demo_bidding_in_app_interstitial_video_320_480_end_card_sound_button), diff --git a/Example/PrebidInternalTestApp/src/main/res/navigation/bidding_navigation.xml b/Example/PrebidInternalTestApp/src/main/res/navigation/bidding_navigation.xml index 790a013d4..b1e892648 100644 --- a/Example/PrebidInternalTestApp/src/main/res/navigation/bidding_navigation.xml +++ b/Example/PrebidInternalTestApp/src/main/res/navigation/bidding_navigation.xml @@ -62,6 +62,15 @@ app:popExitAnim="@anim/nav_default_pop_exit_anim" app:popUpTo="@+id/headerBiddingFragment" /> + + + + Video Interstitial 320x480 Deeplink+ (In-App) Video Interstitial 320x480 SkipOffset (In-App) Video Interstitial 320x480 With End Card (In-App) + Video Interstitial 320x480 With End Card and Close Button Area (In-App) Video Interstitial 320x480 With End Card and Sound Button (In-App) Video Interstitial 320x480 with MRAID End Card (In-App) Video Interstitial 320x480 (In-App) [noBids] From 4c0baa1cdf9540c17e4251fd621df1e08562022f Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 5 Apr 2022 12:28:15 +0300 Subject: [PATCH 4/5] feat(controls): fix tests #388 --- .../org/prebid/mobile/rendering/interstitial/AdBaseDialog.java | 2 +- .../prebid/mobile/rendering/views/video/VideoDialogTest.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java index 110f55597..4b045743a 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java @@ -332,7 +332,7 @@ protected Activity getActivity() { } protected void addCloseView() { - if (mAdViewContainer == null) { + if (mAdViewContainer == null || mInterstitialManager == null) { LogUtil.error(TAG, "Unable to add close button. Container is null"); return; } diff --git a/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/views/video/VideoDialogTest.java b/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/views/video/VideoDialogTest.java index 84ce93cc6..15dda4787 100644 --- a/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/views/video/VideoDialogTest.java +++ b/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/views/video/VideoDialogTest.java @@ -26,6 +26,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.prebid.mobile.rendering.models.InterstitialDisplayPropertiesInternal; import org.prebid.mobile.rendering.video.VideoCreativeView; import org.prebid.mobile.rendering.views.AdViewManager; import org.prebid.mobile.rendering.views.interstitial.InterstitialManager; @@ -68,6 +69,8 @@ public void handleCloseClick_DismissDialog() { @Test public void showBannerCreative_NullAdView() throws IllegalAccessException { + InterstitialDisplayPropertiesInternal propertiesInternal = new InterstitialDisplayPropertiesInternal(); + when(mMockInterstitialManager.getInterstitialDisplayProperties()).thenReturn(propertiesInternal); mVideoDialog.showBannerCreative(mock(View.class)); Object adView = WhiteBox.field(VideoDialog.class, "mAdView").get(mVideoDialog); Assert.assertNull(adView); From bf12a8571d84c7159ca2c4b30a159e7753ca2a1f Mon Sep 17 00:00:00 2001 From: Valentin Petrovych Date: Tue, 5 Apr 2022 14:39:50 +0300 Subject: [PATCH 5/5] feat(controls): create close button position property #389 Make example in Internal test app. Write unit tests. --- .../PpmInterstitialCloseButtonAreaFragment.kt | 2 + .../parallel/BaseInterstitialAdUnit.java | 9 +++ .../rendering/interstitial/AdBaseDialog.java | 2 +- .../InterstitialLayoutConfigurator.java | 1 + ...InterstitialDisplayPropertiesInternal.java | 5 +- .../mobile/rendering/utils/helpers/Utils.java | 60 ++++++++++--------- .../configuration/AdUnitConfiguration.java | 21 ++++++- .../mobile/units/configuration/Position.java | 12 ++++ .../rendering/utils/helpers/UtilsTest.java | 44 +++++++++++++- 9 files changed, 121 insertions(+), 35 deletions(-) create mode 100644 PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/Position.java diff --git a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/ppm/PpmInterstitialCloseButtonAreaFragment.kt b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/ppm/PpmInterstitialCloseButtonAreaFragment.kt index e01629897..8e7df6eb5 100644 --- a/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/ppm/PpmInterstitialCloseButtonAreaFragment.kt +++ b/Example/PrebidInternalTestApp/src/main/java/org/prebid/mobile/renderingtestapp/plugplay/bidding/ppm/PpmInterstitialCloseButtonAreaFragment.kt @@ -3,6 +3,7 @@ package org.prebid.mobile.renderingtestapp.plugplay.bidding.ppm import org.prebid.mobile.rendering.bidding.enums.AdUnitFormat import org.prebid.mobile.rendering.bidding.parallel.InterstitialAdUnit import org.prebid.mobile.renderingtestapp.plugplay.bidding.base.BaseBidInterstitialFragment +import org.prebid.mobile.units.configuration.Position import java.util.* class PpmInterstitialCloseButtonAreaFragment : BaseBidInterstitialFragment() { @@ -21,6 +22,7 @@ class PpmInterstitialCloseButtonAreaFragment : BaseBidInterstitialFragment() { } interstitialAdUnit?.setInterstitialAdUnitListener(this) interstitialAdUnit?.setCloseButtonArea(0.40) + interstitialAdUnit?.setCloseButtonPosition(Position.TOP_LEFT) } } \ No newline at end of file diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/parallel/BaseInterstitialAdUnit.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/parallel/BaseInterstitialAdUnit.java index b1d58960d..320cc73a6 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/parallel/BaseInterstitialAdUnit.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/bidding/parallel/BaseInterstitialAdUnit.java @@ -32,6 +32,7 @@ import org.prebid.mobile.rendering.errors.AdException; import org.prebid.mobile.rendering.models.AdPosition; import org.prebid.mobile.units.configuration.AdUnitConfiguration; +import org.prebid.mobile.units.configuration.Position; import java.lang.ref.WeakReference; import java.util.Map; @@ -191,6 +192,14 @@ public void setCloseButtonArea(@FloatRange(from = 0, to = 1.0) double closeButto adUnitConfig.setCloseButtonArea(closeButtonArea); } + /** + * Sets close button position on the screen. Suitable values TOP_LEFT and TOP_RIGHT. + * Default value TOP_RIGHT. + */ + public void setCloseButtonPosition(@Nullable Position closeButtonPosition) { + adUnitConfig.setCloseButtonPosition(closeButtonPosition); + } + /** * Cleans up resources when destroyed. */ diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java index 4b045743a..578973836 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/AdBaseDialog.java @@ -338,7 +338,7 @@ protected void addCloseView() { } InterstitialDisplayPropertiesInternal properties = mInterstitialManager.getInterstitialDisplayProperties(); - mCloseView = Utils.createCloseView(mContextReference.get(), properties.closeButtonArea); + mCloseView = Utils.createCloseView(mContextReference.get(), properties); if (mCloseView == null) { LogUtil.error(TAG, "Unable to add close button. Close view is null"); diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/InterstitialLayoutConfigurator.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/InterstitialLayoutConfigurator.java index c289e7ace..364d3ef34 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/InterstitialLayoutConfigurator.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/interstitial/InterstitialLayoutConfigurator.java @@ -41,5 +41,6 @@ public static void configureDisplayProperties(AdUnitConfiguration adConfiguratio displayProperties.closeButtonArea = adConfiguration.getCloseButtonArea(); displayProperties.isSoundButtonVisible = adConfiguration.isSoundButtonVisible(); displayProperties.isMuted = adConfiguration.isMuted(); + displayProperties.closeButtonPosition = adConfiguration.getCloseButtonPosition(); } } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/InterstitialDisplayPropertiesInternal.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/InterstitialDisplayPropertiesInternal.java index 18a46004b..b2ae737f8 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/InterstitialDisplayPropertiesInternal.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/models/InterstitialDisplayPropertiesInternal.java @@ -17,18 +17,21 @@ package org.prebid.mobile.rendering.models; import android.content.pm.ActivityInfo; +import org.prebid.mobile.units.configuration.Position; public class InterstitialDisplayPropertiesInternal extends InterstitialDisplayPropertiesPublic { public int expandWidth; public int expandHeight; - public double closeButtonArea; + public double closeButtonArea = 0; public int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; public boolean isSoundButtonVisible = false; public boolean isMuted = false; public boolean isRotationEnabled = false; + public Position closeButtonPosition = Position.TOP_RIGHT; + public void resetExpandValues() { expandHeight = 0; expandWidth = 0; diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java index 0ff6b9f88..45190b68e 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/rendering/utils/helpers/Utils.java @@ -29,18 +29,18 @@ import android.view.*; import android.webkit.MimeTypeMap; import android.widget.FrameLayout; -import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.prebid.mobile.LogUtil; import org.prebid.mobile.core.R; +import org.prebid.mobile.rendering.models.InterstitialDisplayPropertiesInternal; import org.prebid.mobile.rendering.networking.BaseNetworkTask; import org.prebid.mobile.rendering.parser.AdResponseParserVast; import org.prebid.mobile.rendering.video.vast.VAST; +import org.prebid.mobile.units.configuration.Position; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -439,55 +439,57 @@ public static View createCloseView(Context context) { public static View createCloseView( Context context, - @Nullable Double closeButtonArea + InterstitialDisplayPropertiesInternal properties ) { if (context == null) { LogUtil.error(TAG, "Unable to create close view. Context is null"); return null; } - FrameLayout.LayoutParams params; View closeView = LayoutInflater.from(context).inflate(R.layout.lyt_close, null); - if (closeButtonArea == null || closeButtonArea < 0.05 || closeButtonArea > 1) { - params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, - FrameLayout.LayoutParams.WRAP_CONTENT - ); - } else { - int screenSize = getSmallestScreenSideSize(context); - int buttonSize = (int) (screenSize * closeButtonArea); - if (convertPxToDp(buttonSize, context) < MIN_BUTTON_SIZE_DP) { - buttonSize = convertDpToPx(MIN_BUTTON_SIZE_DP, context); - } - int padding = (int) (buttonSize * 0.2); - closeView.setPadding(padding, padding, padding, padding); - params = new FrameLayout.LayoutParams(buttonSize, buttonSize); - } + FrameLayout.LayoutParams params = calculateButtonSize(closeView, properties); params.gravity = Gravity.END | Gravity.TOP; + if (properties != null && properties.closeButtonPosition == Position.TOP_LEFT) { + params.gravity = Gravity.START | Gravity.TOP; + } + closeView.setLayoutParams(params); return closeView; } - public static View createSoundView(Context context) { - return createView(context, R.layout.lyt_sound, Gravity.END | Gravity.BOTTOM); + private static FrameLayout.LayoutParams calculateButtonSize( + View view, + InterstitialDisplayPropertiesInternal properties + ) { + Context context = view.getContext(); + if (properties == null || properties.closeButtonArea < 0.05 || properties.closeButtonArea > 1) { + return new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ); + } + + int screenSize = getSmallestScreenSideSize(context); + int buttonSize = (int) (screenSize * properties.closeButtonArea); + if (convertPxToDp(buttonSize, context) < MIN_BUTTON_SIZE_DP) { + buttonSize = convertDpToPx(MIN_BUTTON_SIZE_DP, context); + } + int padding = (int) (buttonSize * 0.2); + view.setPadding(padding, padding, padding, padding); + return new FrameLayout.LayoutParams(buttonSize, buttonSize); } - private static View createView( - Context context, - @LayoutRes int layoutId, - int gravity - ) { + public static View createSoundView(Context context) { if (context == null) { LogUtil.error(TAG, "Unable to create view. Context is null"); return null; } - View view = LayoutInflater.from(context).inflate(layoutId, null); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, + View view = LayoutInflater.from(context).inflate(R.layout.lyt_sound, null); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT ); - params.gravity = gravity; + params.gravity = Gravity.END | Gravity.BOTTOM; view.setLayoutParams(params); return view; } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/AdUnitConfiguration.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/AdUnitConfiguration.java index 1b0488c99..776e893ef 100644 --- a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/AdUnitConfiguration.java +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/AdUnitConfiguration.java @@ -36,7 +36,7 @@ public class AdUnitConfiguration { private String pbAdSlot; private String interstitialSize; - private final EnumSet adFormats = EnumSet.noneOf(AdFormat.class); + private Position closeButtonPosition = Position.TOP_RIGHT; private AdSize minSizePercentage; private PlacementType placementType; private AdPosition adPosition; @@ -45,6 +45,7 @@ public class AdUnitConfiguration { private VideoBaseAdUnit.Parameters videoParameters; private NativeAdUnitConfiguration nativeConfiguration; + private final EnumSet adFormats = EnumSet.noneOf(AdFormat.class); private final HashSet adSizes = new HashSet<>(); private final ArrayList userDataObjects = new ArrayList<>(); private final Map> contextDataDictionary = new HashMap<>(); @@ -315,7 +316,10 @@ public void setInterstitialSize(@Nullable String size) { interstitialSize = size; } - public void setInterstitialSize(int width, int height) { + public void setInterstitialSize( + int width, + int height + ) { interstitialSize = width + "x" + height; } @@ -324,6 +328,19 @@ public String getInterstitialSize() { return interstitialSize; } + public void setCloseButtonPosition(@Nullable Position closeButtonPosition) { + if (closeButtonPosition != null) { + if (closeButtonPosition == Position.TOP_LEFT || closeButtonPosition == Position.TOP_RIGHT) { + this.closeButtonPosition = closeButtonPosition; + } + } + } + + @NonNull + public Position getCloseButtonPosition() { + return closeButtonPosition; + } + public void setVideoInitialVolume(float videoInitialVolume) { this.videoInitialVolume = videoInitialVolume; } diff --git a/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/Position.java b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/Position.java new file mode 100644 index 000000000..673722c61 --- /dev/null +++ b/PrebidMobile/PrebidMobile-core/src/main/java/org/prebid/mobile/units/configuration/Position.java @@ -0,0 +1,12 @@ +package org.prebid.mobile.units.configuration; + +public enum Position { + TOP_LEFT, + TOP, + TOP_RIGHT, + RIGHT, + BOTTOM_RIGHT, + BOTTOM, + BOTTOM_LEFT, + LEFT +} diff --git a/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/utils/helpers/UtilsTest.java b/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/utils/helpers/UtilsTest.java index 0f0c5510e..764719886 100644 --- a/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/utils/helpers/UtilsTest.java +++ b/PrebidMobile/PrebidMobile-core/src/test/java/org/prebid/mobile/rendering/utils/helpers/UtilsTest.java @@ -37,8 +37,10 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.prebid.mobile.PrebidMobile; +import org.prebid.mobile.rendering.models.InterstitialDisplayPropertiesInternal; import org.prebid.mobile.rendering.networking.BaseNetworkTask; import org.prebid.mobile.test.utils.ResourceUtils; +import org.prebid.mobile.units.configuration.Position; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @@ -424,7 +426,9 @@ public void createCloseView_UseNullCloseButtonArea_CreateViewWithDefaultSize() { public void createCloseView_UseCloseButtonAreaOutOfRange_CreateViewWithDefaultSize() { Activity activity = Robolectric.buildActivity(Activity.class).get(); - View closeView = Utils.createCloseView(activity, 0.0); + InterstitialDisplayPropertiesInternal properties = new InterstitialDisplayPropertiesInternal(); + properties.closeButtonArea = 0.0; + View closeView = Utils.createCloseView(activity, properties); FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); assertEquals(Gravity.END | Gravity.TOP, params.gravity); @@ -436,7 +440,9 @@ public void createCloseView_UseCloseButtonAreaOutOfRange_CreateViewWithDefaultSi public void createCloseView_UseCustomCloseButtonArea_CreateViewWithCalculatedSize() { Activity activity = Robolectric.buildActivity(Activity.class).get(); - View closeView = Utils.createCloseView(activity, 0.2); + InterstitialDisplayPropertiesInternal properties = new InterstitialDisplayPropertiesInternal(); + properties.closeButtonArea = 0.2; + View closeView = Utils.createCloseView(activity, properties); FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); assertEquals(Gravity.END | Gravity.TOP, params.gravity); @@ -445,4 +451,38 @@ public void createCloseView_UseCustomCloseButtonArea_CreateViewWithCalculatedSiz assertEquals(43, closeView.getPaddingTop()); } + @Test + public void createCloseView_UseCustomPosition_CreateViewWithSetPosition() { + Activity activity = Robolectric.buildActivity(Activity.class).get(); + + InterstitialDisplayPropertiesInternal properties = new InterstitialDisplayPropertiesInternal(); + properties.closeButtonPosition = Position.TOP_LEFT; + View closeView = Utils.createCloseView(activity, properties); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); + + assertEquals(Gravity.START | Gravity.TOP, params.gravity); + } + + @Test + public void createCloseView_UseWrongPosition_CreateViewWithDefaultTopRight() { + Activity activity = Robolectric.buildActivity(Activity.class).get(); + + InterstitialDisplayPropertiesInternal properties = new InterstitialDisplayPropertiesInternal(); + properties.closeButtonPosition = Position.BOTTOM; + View closeView = Utils.createCloseView(activity, properties); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); + + assertEquals(Gravity.END | Gravity.TOP, params.gravity); + } + + @Test + public void createCloseView_UseNullProperties_CreateViewWithDefaultTopRight() { + Activity activity = Robolectric.buildActivity(Activity.class).get(); + + View closeView = Utils.createCloseView(activity, null); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) (closeView.getLayoutParams()); + + assertEquals(Gravity.END | Gravity.TOP, params.gravity); + } + }