Skip to content

Commit 3517af1

Browse files
Mobile Ads Developer Relationscopybara-github
authored andcommitted
Add UnityBannerAdPreloader for Next Gen GMA SDK.
This change introduces the UnityBannerAdPreloader class, which wraps the GMA SDK's BannerAdPreloader. It provides methods to start preloading banner ads, check ad availability, poll preloaded ads, and manage preload configurations. Callbacks from the GMA SDK are executed on a separate thread to avoid blocking the Unity main thread. Unit tests are included to verify the functionality of the UnityBannerAdPreloader. PiperOrigin-RevId: 909744560
1 parent 8bf9502 commit 3517af1

5 files changed

Lines changed: 788 additions & 1 deletion

File tree

source/plugin/Assets/Plugins/Android/GoogleMobileAdsPlugin.androidlib/src/main/java/com/google/unity/ads/nextgen/AdWrapper.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.google.unity.ads.nextgen;
22

33
import com.google.android.libraries.ads.mobile.sdk.appopen.AppOpenAd;
4+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAd;
5+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdRequest;
46
import com.google.android.libraries.ads.mobile.sdk.common.AdLoadCallback;
57
import com.google.android.libraries.ads.mobile.sdk.common.AdRequest;
68
import com.google.android.libraries.ads.mobile.sdk.interstitial.InterstitialAd;
@@ -35,6 +37,22 @@ public static AdWrapper<AppOpenAd> forAppOpen() {
3537
return new AdWrapper<>(AppOpenAd::load);
3638
}
3739

40+
/** Creates a new AdWrapper for loading BannerAds. */
41+
public static AdWrapper<BannerAd> forBanner() {
42+
return new AdWrapper<BannerAd>(
43+
new AdLoader<BannerAd>() {
44+
@Override
45+
public void load(AdRequest adRequest, AdLoadCallback<BannerAd> callback) {
46+
if (adRequest instanceof BannerAdRequest) {
47+
BannerAd.load((BannerAdRequest) adRequest, callback);
48+
} else {
49+
throw new IllegalArgumentException(
50+
"AdRequest must be of type BannerAdRequest for Banner Ads");
51+
}
52+
}
53+
});
54+
}
55+
3856
/** Creates a new AdWrapper for loading InterstitialAds. */
3957
public static AdWrapper<InterstitialAd> forInterstitial() {
4058
return new AdWrapper<>(InterstitialAd::load);

source/plugin/Assets/Plugins/Android/GoogleMobileAdsPlugin.androidlib/src/main/java/com/google/unity/ads/nextgen/UnityBannerAd.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import android.widget.FrameLayout;
2727
import androidx.annotation.NonNull;
2828
import androidx.annotation.Nullable;
29+
import androidx.annotation.VisibleForTesting;
2930
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAd;
3031
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdEventCallback;
3132
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdRequest;
@@ -54,9 +55,13 @@ protected static class Insets {
5455
/** The {@link BannerAd} to display to the user. */
5556
private BannerAd bannerAd;
5657

58+
/** The {@link AdWrapper} used to load ads. */
59+
private final AdWrapper<BannerAd> adWrapper;
60+
5761
/** The {@link View} that contains the banner ad. */
5862
private View adView;
5963

64+
6065
/** A code indicating where to place the ad. */
6166
private int positionCode;
6267

@@ -91,8 +96,14 @@ protected static class Insets {
9196
private View.OnLayoutChangeListener layoutChangeListener;
9297

9398
public UnityBannerAd(Activity activity, UnityBannerAdCallback callback) {
99+
this(activity, callback, AdWrapper.forBanner());
100+
}
101+
102+
@VisibleForTesting
103+
UnityBannerAd(Activity activity, UnityBannerAdCallback callback, AdWrapper<BannerAd> adWrapper) {
94104
unityPlayerActivity = activity;
95105
this.callback = callback;
106+
this.adWrapper = adWrapper;
96107
}
97108

98109
/**
@@ -121,7 +132,7 @@ public void create(final int positionX, final int positionY) {
121132
}
122133

123134
protected void load(final BannerAdRequest adRequest) {
124-
BannerAd.load(
135+
adWrapper.load(
125136
adRequest,
126137
new AdLoadCallback<BannerAd>() {
127138
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package com.google.unity.ads.nextgen;
2+
3+
import android.app.Activity;
4+
import androidx.annotation.NonNull;
5+
import androidx.annotation.Nullable;
6+
import androidx.annotation.VisibleForTesting;
7+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAd;
8+
import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdPreloader;
9+
import com.google.android.libraries.ads.mobile.sdk.common.AdLoadCallback;
10+
import com.google.android.libraries.ads.mobile.sdk.common.AdRequest;
11+
import com.google.android.libraries.ads.mobile.sdk.common.LoadAdError;
12+
import com.google.android.libraries.ads.mobile.sdk.common.PreloadCallback;
13+
import com.google.android.libraries.ads.mobile.sdk.common.PreloadConfiguration;
14+
import com.google.android.libraries.ads.mobile.sdk.common.ResponseInfo;
15+
import java.util.Map;
16+
import java.util.concurrent.ExecutorService;
17+
import java.util.concurrent.Executors;
18+
19+
/** Unity implementation of the {@link BannerAdPreloader}. */
20+
public class UnityBannerAdPreloader {
21+
22+
/** The {@code Activity} on which the banner ad will display. */
23+
private final Activity activity;
24+
25+
/** An executor used to run the callbacks. */
26+
private final ExecutorService service;
27+
28+
/**
29+
* A {@code UnityPreloadCallback} implemented in Unity via {@code AndroidJavaProxy} to receive ad
30+
* events.
31+
*/
32+
private final UnityPreloadCallback preloadCallback;
33+
34+
private final BannerAdPreloaderWrapper preloaderWrapper;
35+
36+
public UnityBannerAdPreloader(Activity activity, UnityPreloadCallback preloadCallback) {
37+
this(
38+
activity,
39+
preloadCallback,
40+
new BannerAdPreloaderWrapper(),
41+
Executors.newSingleThreadExecutor());
42+
}
43+
44+
@VisibleForTesting
45+
public UnityBannerAdPreloader(
46+
Activity activity,
47+
UnityPreloadCallback preloadCallback,
48+
BannerAdPreloaderWrapper preloaderWrapper,
49+
ExecutorService service) {
50+
this.activity = activity;
51+
this.preloadCallback = preloadCallback;
52+
this.service = service;
53+
this.preloaderWrapper = preloaderWrapper;
54+
}
55+
56+
public boolean start(String preloadId, PreloadConfiguration preloadConfiguration) {
57+
return preloaderWrapper.start(
58+
preloadId,
59+
preloadConfiguration,
60+
new PreloadCallback() {
61+
@Override
62+
public void onAdPreloaded(@NonNull String preloadId, ResponseInfo responseInfo) {
63+
service.execute(
64+
() -> {
65+
if (preloadCallback != null) {
66+
preloadCallback.onAdPreloaded(preloadId, responseInfo);
67+
}
68+
});
69+
}
70+
71+
@Override
72+
public void onAdsExhausted(@NonNull String preloadId) {
73+
service.execute(
74+
() -> {
75+
if (preloadCallback != null) {
76+
preloadCallback.onAdsExhausted(preloadId);
77+
}
78+
});
79+
}
80+
81+
@Override
82+
public void onAdFailedToPreload(@NonNull String preloadId, @NonNull LoadAdError adError) {
83+
service.execute(
84+
() -> {
85+
if (preloadCallback != null) {
86+
preloadCallback.onAdFailedToPreload(preloadId, adError);
87+
}
88+
});
89+
}
90+
});
91+
}
92+
93+
public boolean isAdAvailable(String preloadId) {
94+
return preloaderWrapper.isAdAvailable(preloadId);
95+
}
96+
97+
public int getNumAdsAvailable(String preloadId) {
98+
return preloaderWrapper.getNumAdsAvailable(preloadId);
99+
}
100+
101+
@SuppressWarnings("VisibleForTests")
102+
@Nullable
103+
public UnityBannerAd pollAd(String preloadId, UnityBannerAdCallback callback) {
104+
final BannerAd pooledAd = preloaderWrapper.pollAd(preloadId);
105+
if (pooledAd == null) {
106+
return null;
107+
}
108+
AdWrapper<BannerAd> preloadedWrapper =
109+
new AdWrapper<BannerAd>(
110+
new AdWrapper.AdLoader<BannerAd>() {
111+
@Override
112+
public void load(AdRequest adRequest, AdLoadCallback<BannerAd> loadCallback) {
113+
loadCallback.onAdLoaded(pooledAd);
114+
}
115+
});
116+
return new UnityBannerAd(activity, callback, preloadedWrapper);
117+
}
118+
119+
@Nullable
120+
public PreloadConfiguration getConfiguration(String preloadId) {
121+
return preloaderWrapper.getConfiguration(preloadId);
122+
}
123+
124+
public Map<String, PreloadConfiguration> getConfigurations() {
125+
return preloaderWrapper.getConfigurations();
126+
}
127+
128+
public void destroy(String preloadId) {
129+
boolean unused = preloaderWrapper.destroy(preloadId);
130+
}
131+
132+
/** Wrapper for BannerAdPreloader static methods to facilitate testing. */
133+
@VisibleForTesting
134+
public static class BannerAdPreloaderWrapper {
135+
public boolean start(String preloadId, PreloadConfiguration config, PreloadCallback callback) {
136+
return BannerAdPreloader.start(preloadId, config, callback);
137+
}
138+
139+
public boolean isAdAvailable(String preloadId) {
140+
return BannerAdPreloader.isAdAvailable(preloadId);
141+
}
142+
143+
public int getNumAdsAvailable(String preloadId) {
144+
return BannerAdPreloader.getNumAdsAvailable(preloadId);
145+
}
146+
147+
public BannerAd pollAd(String preloadId) {
148+
return BannerAdPreloader.pollAd(preloadId);
149+
}
150+
151+
public PreloadConfiguration getConfiguration(String preloadId) {
152+
return BannerAdPreloader.getConfiguration(preloadId);
153+
}
154+
155+
public Map<String, PreloadConfiguration> getConfigurations() {
156+
return BannerAdPreloader.getConfigurations();
157+
}
158+
159+
public boolean destroy(String preloadId) {
160+
return BannerAdPreloader.destroy(preloadId);
161+
}
162+
}
163+
}

0 commit comments

Comments
 (0)