Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(banner): allow adaptive banners to use their container's width #674

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 58 additions & 26 deletions RNGoogleMobileAdsExample/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,8 @@ class InterstitialTest implements Test {
class BannerTest implements Test {
bannerAdSize: BannerAdSize | string;

constructor(bannerAdSize) {
constructor(bannerAdSize: BannerAdSize | string) {
this.bannerAdSize = bannerAdSize;
this.bannerRef = React.createRef();
}

getPath(): string {
Expand All @@ -205,30 +204,11 @@ class BannerTest implements Test {

render(onMount: (component: any) => void): React.ReactNode {
return (
<View ref={onMount}>
<BannerAd
ref={this.bannerRef}
unitId={
this.bannerAdSize.includes('ADAPTIVE_BANNER')
? TestIds.ADAPTIVE_BANNER
: TestIds.BANNER
}
size={this.bannerAdSize}
onPaid={(event: PaidEvent) => {
console.log(
`Paid: ${event.value} ${event.currency} (precision ${
RevenuePrecisions[event.precision]
}})`,
);
}}
/>
<Button
title="reload"
onPress={() => {
this.bannerRef.current?.load();
}}
/>
</View>
<BannerContainer
ref={onMount}
bannerAdSize={this.bannerAdSize}
/>

);
}

Expand All @@ -244,6 +224,58 @@ class BannerTest implements Test {
}
}


class BannerContainer extends React.Component<{ bannerAdSize: string }, { enableContainerAdaptiveMode: boolean }> {
state = {
enableContainerAdaptiveMode: true
}
bannerRef = React.createRef();


render(): React.ReactNode {
return (
<>
<View style={{ width: "50%"}}>
<BannerAd
ref={this.bannerRef}
unitId={
this.props.bannerAdSize.includes('ADAPTIVE_BANNER')
? TestIds.ADAPTIVE_BANNER
: TestIds.BANNER
}
size={this.props.bannerAdSize}
adaptiveMode={this.state.enableContainerAdaptiveMode ? "CONTAINER" : "MAIN_SCREEN"}
onPaid={(event: PaidEvent) => {
console.log(
`Paid: ${event.value} ${event.currency} (precision ${RevenuePrecisions[event.precision]
}})`,
);
}}
/>
</View>
<Button
title="reload"
onPress={() => {
this.bannerRef.current?.load();
}}
/>
<Button
title={
this.state.enableContainerAdaptiveMode
? "Adapt to main screen"
: "Adapt to container"
}
onPress={() => {
this.setState(state => ({
enableContainerAdaptiveMode: !state.enableContainerAdaptiveMode
}))
}}
/>
</>
)
}
}

class CollapsibleBannerTest implements Test {
getPath(): string {
return 'CollapsibleBanner';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,15 @@ public String getName() {
@Nonnull
@Override
public ReactNativeAdView createViewInstance(@Nonnull ThemedReactContext themedReactContext) {
return new ReactNativeAdView(themedReactContext);
ReactNativeAdView reactViewGroup = new ReactNativeAdView(themedReactContext);

reactViewGroup.setWidthChangedConsumer(
(width) -> {
this.updateSizes(reactViewGroup);
this.requestAd(reactViewGroup);
});

return reactViewGroup;
}

@Override
Expand Down Expand Up @@ -120,23 +128,16 @@ public void setRequest(ReactNativeAdView reactViewGroup, String value) {

@ReactProp(name = "sizes")
public void setSizes(ReactNativeAdView reactViewGroup, ReadableArray value) {
List<AdSize> sizeList = new ArrayList<>();
ArrayList<String> sizeList = new ArrayList<>();

for (Object size : value.toArrayList()) {
if (size instanceof String) {
String sizeString = (String) size;
sizeList.add(ReactNativeGoogleMobileAdsCommon.getAdSize(sizeString, reactViewGroup));
sizeList.add((String) size);
}
}

if (sizeList.size() > 0 && !sizeList.contains(AdSize.FLUID)) {
AdSize adSize = sizeList.get(0);
WritableMap payload = Arguments.createMap();
payload.putDouble("width", adSize.getWidth());
payload.putDouble("height", adSize.getHeight());
sendEvent(reactViewGroup, EVENT_SIZE_CHANGE, payload);
}

reactViewGroup.setSizes(sizeList);
reactViewGroup.setRawSizes(sizeList);
this.updateSizes(reactViewGroup);
reactViewGroup.setPropsChanged(true);
}

Expand All @@ -146,6 +147,13 @@ public void setManualImpressionsEnabled(ReactNativeAdView reactViewGroup, boolea
reactViewGroup.setPropsChanged(true);
}

@ReactProp(name = "adaptiveMode")
public void setAdaptiveMode(ReactNativeAdView reactViewGroup, String value) {
reactViewGroup.setAdaptiveMode(value);
this.updateSizes(reactViewGroup);
reactViewGroup.setPropsChanged(true);
}

@Override
public void onAfterUpdateTransaction(@NonNull ReactNativeAdView reactViewGroup) {
super.onAfterUpdateTransaction(reactViewGroup);
Expand All @@ -169,6 +177,23 @@ public void onDropViewInstance(@NonNull ReactNativeAdView reactViewGroup) {
super.onDropViewInstance(reactViewGroup);
}

private void updateSizes(ReactNativeAdView reactViewGroup) {
List<AdSize> sizeList = new ArrayList<>();
for (String size : reactViewGroup.getRawSizes()) {
sizeList.add(ReactNativeGoogleMobileAdsCommon.getAdSize(size, reactViewGroup));
}

if (sizeList.size() > 0 && !sizeList.contains(AdSize.FLUID)) {
AdSize adSize = sizeList.get(0);
WritableMap payload = Arguments.createMap();
payload.putDouble("width", adSize.getWidth());
payload.putDouble("height", adSize.getHeight());
sendEvent(reactViewGroup, EVENT_SIZE_CHANGE, payload);
}

reactViewGroup.setSizes(sizeList);
}

private BaseAdView initAdView(ReactNativeAdView reactViewGroup) {
BaseAdView oldAdView = getAdView(reactViewGroup);
if (oldAdView != null) {
Expand Down Expand Up @@ -282,7 +307,11 @@ private void requestAd(ReactNativeAdView reactViewGroup) {
AdRequest request = reactViewGroup.getRequest();
Boolean manualImpressionsEnabled = reactViewGroup.getManualImpressionsEnabled();

if (sizes == null || unitId == null || request == null || manualImpressionsEnabled == null) {
if (sizes == null
|| sizes.get(0).getWidth() == 0
|| unitId == null
|| request == null
|| manualImpressionsEnabled == null) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.ViewGroup;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableMap;
Expand All @@ -30,6 +29,7 @@
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.admanager.AdManagerAdRequest;
import io.invertase.googlemobileads.common.ReactNativeAdView;
import io.invertase.googlemobileads.common.ReactNativeEventEmitter;
import java.util.ArrayList;
import java.util.Map;
Expand All @@ -40,17 +40,49 @@

public class ReactNativeGoogleMobileAdsCommon {

static AdSize getAdSizeForAdaptiveBanner(String preDefinedAdSize, ViewGroup reactViewGroup) {
static DisplayMetrics getDisplayOutMetrics(ReactNativeAdView reactViewGroup) {
Display display =
Objects.requireNonNull(((ReactContext) reactViewGroup.getContext()).getCurrentActivity())
.getWindowManager()
.getDefaultDisplay();

DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);

return outMetrics;
}

static int getWindowWidth(ReactNativeAdView reactViewGroup) {
DisplayMetrics outMetrics =
ReactNativeGoogleMobileAdsCommon.getDisplayOutMetrics(reactViewGroup);
return (int) (outMetrics.widthPixels / outMetrics.density);
}

static int getViewWidth(ReactNativeAdView reactViewGroup) {
DisplayMetrics outMetrics =
ReactNativeGoogleMobileAdsCommon.getDisplayOutMetrics(reactViewGroup);
return (int) (reactViewGroup.getViewWidth() / outMetrics.density);
}

static AdSize getAdSizeForAdaptiveBanner(
String preDefinedAdSize, ReactNativeAdView reactViewGroup) {

try {
Display display =
Objects.requireNonNull(((ReactContext) reactViewGroup.getContext()).getCurrentActivity())
.getWindowManager()
.getDefaultDisplay();
String adaptiveMode = reactViewGroup.getAdaptiveMode();

if (adaptiveMode == null) {
return new AdSize(0, 0);
}

int adWidth = getViewWidth(reactViewGroup);

DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
int adWidth = (int) (outMetrics.widthPixels / outMetrics.density);
if (!adaptiveMode.equals("CONTAINER")) {
adWidth = ReactNativeGoogleMobileAdsCommon.getWindowWidth(reactViewGroup);
}

if (adWidth == 0) {
return new AdSize(0, 0);
}

if ("INLINE_ADAPTIVE_BANNER".equals(preDefinedAdSize)) {
return AdSize.getCurrentOrientationInlineAdaptiveBannerAdSize(
Expand All @@ -63,7 +95,7 @@ static AdSize getAdSizeForAdaptiveBanner(String preDefinedAdSize, ViewGroup reac
}
}

static AdSize getAdSize(String preDefinedAdSize, ViewGroup reactViewGroup) {
static AdSize getAdSize(String preDefinedAdSize, ReactNativeAdView reactViewGroup) {
if (preDefinedAdSize.matches(
"ADAPTIVE_BANNER|ANCHORED_ADAPTIVE_BANNER|INLINE_ADAPTIVE_BANNER")) {
return ReactNativeGoogleMobileAdsCommon.getAdSizeForAdaptiveBanner(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import java.util.List;
import java.util.function.Consumer;

/**
* Using FrameLayout instead of ReactViewGroup
Expand All @@ -18,10 +19,14 @@
public class ReactNativeAdView extends FrameLayout {
private AdRequest request;
private List<AdSize> sizes;
private List<String> rawSizes;
private String unitId;
private boolean manualImpressionsEnabled;
private boolean propsChanged;
private boolean isFluid;
private String adaptiveMode;
private int viewWidth = 0;
private Consumer<Integer> widthChangedConsumer;

@Override
public void requestLayout() {
Expand Down Expand Up @@ -74,6 +79,14 @@ public List<AdSize> getSizes() {
return this.sizes;
}

public void setRawSizes(List<String> rawSizes) {
this.rawSizes = rawSizes;
}

public List<String> getRawSizes() {
return this.rawSizes;
}

public void setUnitId(String unitId) {
this.unitId = unitId;
}
Expand Down Expand Up @@ -105,4 +118,33 @@ public void setIsFluid(boolean isFluid) {
public boolean getIsFluid() {
return this.isFluid;
}

public void setAdaptiveMode(String adaptiveMode) {
this.adaptiveMode = adaptiveMode;
}

public String getAdaptiveMode() {
return this.adaptiveMode;
}

public int getViewWidth() {
return this.viewWidth;
}

public void setWidthChangedConsumer(Consumer<Integer> consumer) {
this.widthChangedConsumer = consumer;
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);

this.viewWidth = w;

if (!adaptiveMode.equals("CONTAINER") || widthChangedConsumer == null || w == oldw) {
return;
}

widthChangedConsumer.accept(viewWidth);
}
}
4 changes: 4 additions & 0 deletions ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@

@interface RNGoogleMobileAdsBannerComponent : RCTView <GADBannerViewDelegate, GADAppEventDelegate>

@property CGFloat viewWidth;

@property GADBannerView *banner;
@property(nonatomic, assign) BOOL requested;

@property(nonatomic, copy) NSArray *rawSizes;
@property(nonatomic, copy) NSArray *sizes;
@property(nonatomic, copy) NSString *unitId;
@property(nonatomic, copy) NSDictionary *request;
@property(nonatomic, copy) NSNumber *manualImpressionsEnabled;
@property(nonatomic, copy) NSString *adaptiveMode;
@property(nonatomic, assign) BOOL propsChanged;

@property(nonatomic, copy) RCTBubblingEventBlock onNativeEvent;
Expand Down
Loading
Loading