Skip to content

Commit

Permalink
Interstitial video fixes (#469)
Browse files Browse the repository at this point in the history
* feat: make interstitial ad fullscreen and fix cutouts #462

Fix close, counter, and learn more button positions when there are cutouts or bottom navigation. Create custom theme for all interstitial ads.

* fix: read timeout for file download tasks #462

* fix: increase creative factory timeout for interstitial cases #462

* fix: buttons visibility in interstitial ads #462

Fix Learn more button position. Show Learn more button in every video interstitial ad.  Show count down button only for rewarded.

* fix: insets fixes #462

Fix insets for other orientations.

* fix: displaying Learn more #462

* fix: button positions after rotation #462

* fix: scaling end cards for any resolution #462
  • Loading branch information
ValentinPostindustria authored Jun 4, 2022
1 parent b9b3ca6 commit 55dc976
Show file tree
Hide file tree
Showing 17 changed files with 377 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.prebid.mobile.api.rendering;

import android.content.Context;
import android.content.res.Configuration;
import android.util.Log;
import android.view.View;
import org.prebid.mobile.LogUtil;
Expand All @@ -29,18 +30,39 @@
import org.prebid.mobile.rendering.models.AdDetails;
import org.prebid.mobile.rendering.models.internal.InternalFriendlyObstruction;
import org.prebid.mobile.rendering.utils.constants.IntentActions;
import org.prebid.mobile.rendering.utils.helpers.InsetsUtils;
import org.prebid.mobile.rendering.views.AdViewManager;
import org.prebid.mobile.rendering.views.AdViewManagerListener;
import org.prebid.mobile.rendering.views.base.BaseAdView;
import org.prebid.mobile.rendering.views.interstitial.InterstitialVideo;

import java.util.Arrays;
import java.util.List;

public class InterstitialView extends BaseAdView {

private static final String TAG = InterstitialView.class.getSimpleName();

private InterstitialViewListener listener;
protected InterstitialVideo interstitialVideo;

@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);

List<View> views = Arrays.asList(
findViewById(R.id.iv_close_interstitial),
findViewById(R.id.iv_skip),
findViewById(R.id.rl_count_down),
findViewById(R.id.tv_learn_more)
);

for (View view : views) {
InsetsUtils.resetMargins(view);
InsetsUtils.addCutoutAndNavigationInsets(view);
}
}

//region ========== Listener Area
private final AdViewManagerListener onAdViewManagerListener = new AdViewManagerListener() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,23 @@ public void onError(Throwable throwable) {
};
private DialogEventListener listener;

public AdBaseDialog(Context context, int theme, InterstitialManager interstitialManager) {
super(context, theme);
public AdBaseDialog(
Context context,
InterstitialManager interstitialManager
) {
super(context, R.style.FullScreenDialogTheme);
contextReference = new WeakReference<>(context);
this.interstitialManager = interstitialManager;

setOnShowListener(new OnDialogShowListener(this));
}

public AdBaseDialog(Context context, WebViewBase webViewBaseLocal, InterstitialManager interstitialManager) {
super(context, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
public AdBaseDialog(
Context context,
WebViewBase webViewBaseLocal,
InterstitialManager interstitialManager
) {
super(context, R.style.FullScreenDialogTheme);

contextReference = new WeakReference<>(context);
webViewBase = webViewBaseLocal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class CreativeFactory {
private static final String TAG = CreativeFactory.class.getSimpleName();
private static final long BANNER_TIMEOUT = 6 * 1000;
private static final long VAST_TIMEOUT = 30 * 1000;
private static final long INTERSTITIAL_TIMEOUT = 30 * 1000;

private AbstractCreative creative;
private CreativeModel creativeModel;
Expand Down Expand Up @@ -141,7 +142,12 @@ private void attemptAuidCreative() throws Exception {
} else {
listener.onFailure(new AdException(AdException.INTERNAL_ERROR, "Tracking info not found"));
}
markWorkStart(BANNER_TIMEOUT);

long creativeDownloadTimeout = BANNER_TIMEOUT;
if (creativeModel.getAdConfiguration().isAdType(AdFormat.INTERSTITIAL)) {
creativeDownloadTimeout = INTERSTITIAL_TIMEOUT;
}
markWorkStart(creativeDownloadTimeout);
creative.load();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.http.conn.ConnectTimeoutException;
import org.prebid.mobile.LogUtil;
import org.prebid.mobile.PrebidMobile;
import org.prebid.mobile.rendering.loading.FileDownloadTask;
import org.prebid.mobile.rendering.networking.exception.BaseExceptionHolder;
import org.prebid.mobile.rendering.utils.helpers.Utils;

Expand Down Expand Up @@ -248,8 +249,10 @@ private URLConnection setHttpURLConnectionProperty(GetUrlParams param) throws Ex
connection.setRequestProperty(CONTENT_TYPE_HEADER, CONTENT_TYPE_HEADER_VALUE);
this.setCustomHeadersIfAvailable(connection);

connection.setReadTimeout(SOCKET_TIMEOUT);
connection.setConnectTimeout(PrebidMobile.getTimeoutMillis());
if (!(this instanceof FileDownloadTask)) {
connection.setReadTimeout(SOCKET_TIMEOUT);
}

if ("POST".equals(param.requestType)) {
// Send post request
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.prebid.mobile.rendering.utils.helpers;

public class CustomInsets {

private int top;
private int right;
private int bottom;
private int left;

public CustomInsets(
int top,
int right,
int bottom,
int left
) {
this.top = top;
this.right = right;
this.bottom = bottom;
this.left = left;
}

public int getTop() {
return top;
}

public void setTop(int top) {
this.top = top;
}

public int getRight() {
return right;
}

public void setRight(int right) {
this.right = right;
}

public int getBottom() {
return bottom;
}

public void setBottom(int bottom) {
this.bottom = bottom;
}

public int getLeft() {
return left;
}

public void setLeft(int left) {
this.left = left;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package org.prebid.mobile.rendering.utils.helpers;

import android.app.Activity;
import android.content.Context;
import android.graphics.Insets;
import android.os.Build;
import android.view.*;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import androidx.annotation.Nullable;
import org.prebid.mobile.LogUtil;

public class InsetsUtils {

private static final String TAG = InsetsUtils.class.getSimpleName();

/**
* Adds to the view insets from navigation bar and cutout.
* Insets must be calculated as we use translucent status and navigation bar in
* interstitial ad. Must be applied to every view in interstitial ad.
* <p>
* It supports view where parents are RelativeLayout or FrameLayout.
*/
public static void addCutoutAndNavigationInsets(@Nullable View view) {
if (view == null) return;
ViewGroup.LayoutParams params = view.getLayoutParams();
CustomInsets navigationInsets = getNavigationInsets(view.getContext());
CustomInsets cutoutInsets = getCutoutInsets(view.getContext());
CustomInsets insets = new CustomInsets(
navigationInsets.getTop() + cutoutInsets.getTop(),
navigationInsets.getRight() + cutoutInsets.getRight(),
navigationInsets.getBottom() + cutoutInsets.getBottom(),
navigationInsets.getLeft() + cutoutInsets.getLeft()
);

if (params instanceof FrameLayout.LayoutParams) {
FrameLayout.LayoutParams frameParams = (FrameLayout.LayoutParams) params;
int gravity = frameParams.gravity;
if ((gravity & Gravity.TOP) == Gravity.TOP) {
frameParams.topMargin += insets.getTop();
}
if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
frameParams.bottomMargin += insets.getBottom();
}
if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
frameParams.rightMargin += insets.getRight();
}
if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
frameParams.leftMargin += insets.getLeft();
}
view.setLayoutParams(frameParams);
} else if (params instanceof RelativeLayout.LayoutParams) {
RelativeLayout.LayoutParams relativeParams = (RelativeLayout.LayoutParams) params;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (relativeParams.getRule(RelativeLayout.ALIGN_PARENT_TOP) == RelativeLayout.TRUE) {
relativeParams.topMargin += insets.getTop();
}
if (relativeParams.getRule(RelativeLayout.ALIGN_PARENT_BOTTOM) == RelativeLayout.TRUE) {
relativeParams.bottomMargin += insets.getBottom();
}
if (relativeParams.getRule(RelativeLayout.ALIGN_PARENT_RIGHT) == RelativeLayout.TRUE
|| relativeParams.getRule(RelativeLayout.ALIGN_PARENT_END) == RelativeLayout.TRUE
) {
relativeParams.rightMargin += insets.getRight();
}
if (relativeParams.getRule(RelativeLayout.ALIGN_PARENT_LEFT) == RelativeLayout.TRUE
|| relativeParams.getRule(RelativeLayout.ALIGN_PARENT_START) == RelativeLayout.TRUE
) {
relativeParams.leftMargin += insets.getLeft();
}
}
view.setLayoutParams(relativeParams);
} else {
LogUtil.error(TAG, "Can't set insets, unsupported LayoutParams type.");
}
}

public static CustomInsets getCutoutInsets(Context context) {
if (context != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
DisplayCutout cutout = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
cutout = context.getDisplay().getCutout();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (context instanceof Activity) {
Activity activity = (Activity) context;
cutout = activity.getWindowManager().getDefaultDisplay().getCutout();
}
} else {
WindowInsets windowInsets = getWindowInsets(context);
if (windowInsets != null) {
cutout = windowInsets.getDisplayCutout();
}
}
if (cutout != null) {
return new CustomInsets(
cutout.getSafeInsetTop(),
cutout.getSafeInsetRight(),
cutout.getSafeInsetBottom(),
cutout.getSafeInsetLeft()
);
}
}
return new CustomInsets(0, 0, 0, 0);
}

public static CustomInsets getNavigationInsets(Context context) {
WindowInsets windowInsets = getWindowInsets(context);
if (windowInsets != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Insets insets = windowInsets.getInsets(WindowInsets.Type.navigationBars());
return new CustomInsets(insets.top, insets.right, insets.bottom, insets.left);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// noinspection deprecation
return new CustomInsets(
windowInsets.getStableInsetTop(),
windowInsets.getStableInsetRight(),
windowInsets.getStableInsetBottom(),
windowInsets.getStableInsetLeft()
);
}
}
return new CustomInsets(0, 0, 0, 0);
}

public static void resetMargins(@Nullable View view) {
int defaultMargin = 16;
if (view != null) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (params instanceof FrameLayout.LayoutParams) {
FrameLayout.LayoutParams frameParams = (FrameLayout.LayoutParams) params;
frameParams.setMargins(defaultMargin, defaultMargin, defaultMargin, defaultMargin);
view.setLayoutParams(frameParams);
} else if (params instanceof RelativeLayout.LayoutParams) {
RelativeLayout.LayoutParams relativeParams = (RelativeLayout.LayoutParams) params;
relativeParams.setMargins(defaultMargin, defaultMargin, defaultMargin, defaultMargin);
view.setLayoutParams(relativeParams);
} else {
LogUtil.debug(TAG, "Can't reset margins.");
}
}
}

@Nullable
private static WindowInsets getWindowInsets(@Nullable Context context) {
if (context != null) {
if (context instanceof Activity) {
Activity activity = (Activity) context;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return activity.getWindow().getDecorView().getRootWindowInsets();
}
} else {
LogUtil.debug(TAG, "Can't get window insets, Context is not Activity type.");
}
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -472,20 +472,24 @@ private static View createButtonToNextPage(
}

view.setLayoutParams(params);
InsetsUtils.addCutoutAndNavigationInsets(view);
return view;
}

private static final int MIN_BUTTON_SIZE_DP = 30;
private static final int MIN_BUTTON_SIZE_DP = 25;

private static FrameLayout.LayoutParams calculateButtonSize(
View view,
double closeButtonArea
) {
Context context = view.getContext();

if (closeButtonArea < 0.05 || closeButtonArea > 1) {
return new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
);
return layoutParams;
}

int screenSize = getSmallestScreenSideSize(context);
Expand All @@ -505,8 +509,9 @@ public static View createSoundView(Context context) {
}

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
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
params.gravity = Gravity.END | Gravity.BOTTOM;
view.setLayoutParams(params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,10 @@ protected void complete() {
}

protected void showCallToAction() {
if (!model.getAdConfiguration()
.isBuiltInVideo() && Utils.isNotBlank(model.getVastClickthroughUrl()) && !model.hasEndCard()) {
if (!model.getAdConfiguration().isBuiltInVideo()
&& Utils.isNotBlank(model.getVastClickthroughUrl())
&& !model.getAdConfiguration().isRewarded()
) {
videoCreativeView.showCallToAction();
}
}
Expand Down
Loading

0 comments on commit 55dc976

Please sign in to comment.