Skip to content

Commit

Permalink
feat: adaptive banner with container width and adaptive height
Browse files Browse the repository at this point in the history
  • Loading branch information
youssef eddibili committed Dec 23, 2024
1 parent fd5726b commit 45cd51c
Show file tree
Hide file tree
Showing 14 changed files with 518 additions and 236 deletions.
121 changes: 79 additions & 42 deletions RNGoogleMobileAdsExample/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useEffect, useRef} from 'react';
import React, { useEffect, useRef } from 'react';
import {
Button,
Platform,
Expand All @@ -8,7 +8,7 @@ import {
Text,
View,
} from 'react-native';
import {Test, TestRegistry, TestResult, TestRunner, TestType} from 'jet';
import { Test, TestRegistry, TestResult, TestRunner, TestType } from 'jet';

import MobileAds, {
type PaidEvent,
Expand Down Expand Up @@ -44,7 +44,7 @@ class AppOpenTest implements Test {

constructor() {
// Current no way in jet-next to re-render on async completion or to delay render? But still can log it
this.adListener = appOpen.addAdEventsListener(({type, payload}) => {
this.adListener = appOpen.addAdEventsListener(({ type, payload }) => {
console.log(`${Platform.OS} app open ad event: ${type}`);
if (type === AdEventType.PAID) {
console.log(payload);
Expand Down Expand Up @@ -119,7 +119,7 @@ class InterstitialTest implements Test {

constructor() {
// Current no way in jet-next to re-render on async completion or to delay render? But still can log it
this.adListener = interstitial.addAdEventsListener(({type, payload}) => {
this.adListener = interstitial.addAdEventsListener(({ type, payload }) => {
console.log(`${Platform.OS} interstitial ad event: ${type}`);
if (type === AdEventType.PAID) {
console.log('Paid', payload);
Expand Down Expand Up @@ -182,12 +182,64 @@ class InterstitialTest 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 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 +257,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 Down Expand Up @@ -291,7 +324,7 @@ class RewardedTest implements Test {

constructor() {
// Current no way in jet-next to re-render on async completion or to delay render? But still can log it
this.adListener = rewarded.addAdEventsListener(({type, payload}) => {
this.adListener = rewarded.addAdEventsListener(({ type, payload }) => {
console.log(`${Platform.OS} rewarded ad event: ${type}`);
if (type === AdEventType.PAID) {
console.log(payload);
Expand Down Expand Up @@ -371,15 +404,14 @@ class RewardedInterstitialTest implements Test {
constructor() {
// Current no way in jet-next to re-render on async completion or to delay render? But still can log it
this.adListener = rewardedInterstitial.addAdEventsListener(
({type, payload}) => {
({ type, payload }) => {
console.log(`${Platform.OS} rewarded interstitial ad event: ${type}`);
if (type === AdEventType.PAID) {
console.log(payload);
}
if (type === AdEventType.ERROR) {
console.log(
`${Platform.OS} rewarded interstitial error: ${
(payload as Error).message
`${Platform.OS} rewarded interstitial error: ${(payload as Error).message
}`,
);
}
Expand Down Expand Up @@ -496,7 +528,7 @@ class AdConsentTest implements Test {
}

const InterstitialHookComponent = React.forwardRef<View>((_, ref) => {
const {load, show, error, isLoaded, isClicked, isClosed, isOpened, revenue} =
const { load, show, error, isLoaded, isClicked, isClosed, isOpened, revenue } =
useInterstitialAd(TestIds.INTERSTITIAL);
useEffect(() => {
load();
Expand Down Expand Up @@ -707,7 +739,7 @@ class RewardedInterstitialHookTest implements Test {
}

const AppOpenHookComponent = React.forwardRef<View>((_, ref) => {
const {load, show, error, isLoaded, isClicked, isClosed, isOpened} =
const { load, show, error, isLoaded, isClicked, isClosed, isOpened } =
useAppOpenAd(TestIds.APP_OPEN);
useEffect(() => {
load();
Expand Down Expand Up @@ -802,13 +834,18 @@ const GAMBannerComponent = React.forwardRef<
unitId: string;
sizes: GAMBannerAdSize[];
}
>(({unitId, sizes}, ref) => {
>(({ unitId, sizes }, ref) => {
const bannerRef = useRef<GAMBannerAd>(null);
const recordManualImpression = () => {
bannerRef.current?.recordManualImpression();
};
return (
<View ref={ref}>
<View
style={{
backgroundColor: 'red',
width: 390
}}
ref={ref}>
{/* To test FLUID size ad, use `TestIds.GAM_NATIVE` */}
<GAMBannerAd
ref={bannerRef}
Expand All @@ -817,6 +854,7 @@ const GAMBannerComponent = React.forwardRef<
requestOptions={{
requestNonPersonalizedAdsOnly: true,
}}
adaptiveMode='CONTAINER'
manualImpressionsEnabled={true}
onAdFailedToLoad={(error: Error) => {
console.log(`${Platform.OS} GAM banner error: ${error.message}`);
Expand All @@ -832,7 +870,7 @@ class GAMBannerTest implements Test {
unitId: string;
sizes: GAMBannerAdSize[];
},
) {}
) { }

getPath(): string {
return (
Expand Down Expand Up @@ -886,12 +924,11 @@ class GAMInterstitialTest implements Test {

constructor() {
// Current no way in jet-next to re-render on async completion or to delay render? But still can log it
this.adListener = gamInterstitial.addAdEventsListener(({type, payload}) => {
this.adListener = gamInterstitial.addAdEventsListener(({ type, payload }) => {
console.log(`${Platform.OS} GAM interstitial ad event: ${type}`);
if (type === AdEventType.ERROR) {
console.log(
`${Platform.OS} GAM interstitial error: ${
(payload as Error).message
`${Platform.OS} GAM interstitial error: ${(payload as Error).message
}`,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
* limitations under the License.
*
*/

import android.app.Activity;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
Expand Down Expand Up @@ -73,7 +72,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 +127,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 +146,13 @@ public void setManualImpressionsEnabled(ReactNativeAdView reactViewGroup, boolea
reactViewGroup.setPropsChanged(true);
}

@ReactProp(name = "adaptiveMode")
public void setManualImpressionsEnabled(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 +176,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 +306,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
Loading

0 comments on commit 45cd51c

Please sign in to comment.