Skip to content

Commit e4c1a94

Browse files
committed
Allow serving Banner ads in AdLoaderAd
Allow the `AdLoaderAd` instance to serve `Banner` ads, which are instances of: * `AdManagerAdView` under Android, and * `GAMBannerView` under iOS
1 parent f7804a7 commit e4c1a94

23 files changed

Lines changed: 1141 additions & 33 deletions

packages/google_mobile_ads/android/src/main/java/io/flutter/plugins/googlemobileads/AdMessageCodec.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class AdMessageCodec extends StandardMessageCodec {
6565
private static final byte VALUE_NATIVE_TEMPLATE_FONT_STYLE = (byte) 151;
6666
private static final byte VALUE_NATIVE_TEMPLATE_TYPE = (byte) 152;
6767
private static final byte VALUE_COLOR = (byte) 153;
68+
private static final byte VALUE_AD_MANAGER_AD_VIEW_OPTIONS = (byte) 154;
69+
private static final byte VALUE_BANNER_PARAMETERS = (byte) 155;
6870

6971
@NonNull Context context;
7072
@NonNull final FlutterAdSize.AdSizeFactory adSizeFactory;
@@ -242,6 +244,15 @@ protected void writeValue(ByteArrayOutputStream stream, Object value) {
242244
writeValue(stream, Color.red(colorValue));
243245
writeValue(stream, Color.green(colorValue));
244246
writeValue(stream, Color.blue(colorValue));
247+
} else if (value instanceof FlutterAdManagerAdViewOptions) {
248+
stream.write(VALUE_AD_MANAGER_AD_VIEW_OPTIONS);
249+
FlutterAdManagerAdViewOptions options = (FlutterAdManagerAdViewOptions) value;
250+
writeValue(stream, options.manualImpressionsEnabled);
251+
} else if (value instanceof FlutterBannerParameters) {
252+
stream.write(VALUE_BANNER_PARAMETERS);
253+
FlutterBannerParameters bannerParameters = (FlutterBannerParameters) value;
254+
writeValue(stream, bannerParameters.sizes);
255+
writeValue(stream, bannerParameters.adManagerAdViewOptions);
245256
} else {
246257
super.writeValue(stream, value);
247258
}
@@ -402,6 +413,12 @@ protected Object readValueOfType(byte type, ByteBuffer buffer) {
402413
final Integer green = (Integer) readValueOfType(buffer.get(), buffer);
403414
final Integer blue = (Integer) readValueOfType(buffer.get(), buffer);
404415
return new ColorDrawable(Color.argb(alpha, red, green, blue));
416+
case VALUE_AD_MANAGER_AD_VIEW_OPTIONS:
417+
return new FlutterAdManagerAdViewOptions((Boolean) readValueOfType(buffer.get(), buffer));
418+
case VALUE_BANNER_PARAMETERS:
419+
return new FlutterBannerParameters(
420+
(List<FlutterAdSize>) readValueOfType(buffer.get(), buffer),
421+
(FlutterAdManagerAdViewOptions) readValueOfType(buffer.get(), buffer));
405422
default:
406423
return super.readValueOfType(type, buffer);
407424
}

packages/google_mobile_ads/android/src/main/java/io/flutter/plugins/googlemobileads/FlutterAdListener.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import androidx.annotation.NonNull;
1717
import com.google.android.gms.ads.AdListener;
1818
import com.google.android.gms.ads.LoadAdError;
19+
import com.google.android.gms.ads.admanager.AdManagerAdView;
20+
import com.google.android.gms.ads.formats.OnAdManagerAdViewLoadedListener;
1921
import com.google.android.gms.ads.nativead.NativeAd;
2022
import com.google.android.gms.ads.nativead.NativeAd.OnNativeAdLoadedListener;
2123
import java.lang.ref.WeakReference;
@@ -118,3 +120,20 @@ public void onNativeAdLoaded(@NonNull NativeAd nativeAd) {
118120
}
119121
}
120122
}
123+
124+
/** {@link OnAdManagerAdViewLoadedListener} for banner ads. */
125+
class FlutterAdManagerAdViewLoadedListener implements OnAdManagerAdViewLoadedListener {
126+
127+
private final WeakReference<OnAdManagerAdViewLoadedListener> reference;
128+
129+
FlutterAdManagerAdViewLoadedListener(OnAdManagerAdViewLoadedListener listener) {
130+
reference = new WeakReference<>(listener);
131+
}
132+
133+
@Override
134+
public void onAdManagerAdViewLoaded(AdManagerAdView adView) {
135+
if (reference.get() != null) {
136+
reference.get().onAdManagerAdViewLoaded(adView);
137+
}
138+
}
139+
}

packages/google_mobile_ads/android/src/main/java/io/flutter/plugins/googlemobileads/FlutterAdLoader.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import android.content.Context;
1818
import androidx.annotation.NonNull;
19+
import androidx.annotation.Nullable;
1920
import com.google.android.gms.ads.AdListener;
2021
import com.google.android.gms.ads.AdLoader;
2122
import com.google.android.gms.ads.AdRequest;
@@ -142,18 +143,33 @@ public void loadAdManagerNativeAd(
142143

143144
/** Load an ad loader ad. */
144145
public void loadAdLoaderAd(
145-
@NonNull String adUnitId, @NonNull AdListener adListener, @NonNull AdRequest request) {
146-
new AdLoader.Builder(context, adUnitId).withAdListener(adListener).build().loadAd(request);
146+
@NonNull String adUnitId,
147+
@NonNull AdListener adListener,
148+
@NonNull AdRequest request,
149+
@Nullable FlutterAdLoaderAd.BannerParameters bannerParameters) {
150+
AdLoader.Builder builder = new AdLoader.Builder(context, adUnitId);
151+
if (bannerParameters != null) {
152+
builder = builder.forAdManagerAdView(bannerParameters.listener, bannerParameters.adSizes);
153+
if (bannerParameters.adManagerAdViewOptions != null) {
154+
builder.withAdManagerAdViewOptions(bannerParameters.adManagerAdViewOptions);
155+
}
156+
}
157+
builder.withAdListener(adListener).build().loadAd(request);
147158
}
148159

149160
/** Load an ad manager ad loader ad. */
150161
public void loadAdManagerAdLoaderAd(
151162
@NonNull String adUnitId,
152163
@NonNull AdListener adListener,
153-
@NonNull AdManagerAdRequest adManagerAdRequest) {
154-
new AdLoader.Builder(context, adUnitId)
155-
.withAdListener(adListener)
156-
.build()
157-
.loadAd(adManagerAdRequest);
164+
@NonNull AdManagerAdRequest adManagerAdRequest,
165+
@Nullable FlutterAdLoaderAd.BannerParameters bannerParameters) {
166+
AdLoader.Builder builder = new AdLoader.Builder(context, adUnitId);
167+
if (bannerParameters != null) {
168+
builder = builder.forAdManagerAdView(bannerParameters.listener, bannerParameters.adSizes);
169+
if (bannerParameters.adManagerAdViewOptions != null) {
170+
builder.withAdManagerAdViewOptions(bannerParameters.adManagerAdViewOptions);
171+
}
172+
}
173+
builder.withAdListener(adListener).build().loadAd(adManagerAdRequest);
158174
}
159175
}

packages/google_mobile_ads/android/src/main/java/io/flutter/plugins/googlemobileads/FlutterAdLoaderAd.java

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,22 @@
1515
package io.flutter.plugins.googlemobileads;
1616

1717
import android.util.Log;
18+
import android.view.View;
1819
import androidx.annotation.NonNull;
1920
import androidx.annotation.Nullable;
2021
import com.google.android.gms.ads.AdListener;
22+
import com.google.android.gms.ads.AdSize;
23+
import com.google.android.gms.ads.BaseAdView;
24+
import com.google.android.gms.ads.admanager.AdManagerAdView;
25+
import com.google.android.gms.ads.formats.AdManagerAdViewOptions;
26+
import com.google.android.gms.ads.formats.OnAdManagerAdViewLoadedListener;
27+
import io.flutter.plugin.platform.PlatformView;
2128

2229
/**
2330
* A central wrapper for {@link AdManagerAdView}, {@link NativeCustomFormatAd} and {@link NativeAd}
2431
* instances served for a single {@link AdRequest} or {@link AdManagerAdRequest}
2532
*/
26-
class FlutterAdLoaderAd extends FlutterAd {
33+
class FlutterAdLoaderAd extends FlutterAd implements OnAdManagerAdViewLoadedListener {
2734
private static final String TAG = "FlutterAdLoaderAd";
2835

2936
@NonNull private final AdInstanceManager manager;
@@ -33,6 +40,8 @@ class FlutterAdLoaderAd extends FlutterAd {
3340
@Nullable private FlutterAdManagerAdRequest adManagerRequest;
3441
@Nullable private AdLoaderAdType type;
3542
@Nullable private String formatId;
43+
@Nullable private View view;
44+
@Nullable protected BannerParameters bannerParameters;
3645

3746
static class Builder {
3847
@Nullable private AdInstanceManager manager;
@@ -41,6 +50,7 @@ static class Builder {
4150
@Nullable private FlutterAdManagerAdRequest adManagerRequest;
4251
@Nullable private Integer id;
4352
@Nullable private FlutterAdLoader adLoader;
53+
@Nullable private FlutterBannerParameters bannerParameters;
4454

4555
public Builder setId(int id) {
4656
this.id = id;
@@ -72,6 +82,11 @@ public Builder setFlutterAdLoader(@NonNull FlutterAdLoader adLoader) {
7282
return this;
7383
}
7484

85+
public Builder setBanner(@Nullable FlutterBannerParameters bannerParameters) {
86+
this.bannerParameters = bannerParameters;
87+
return this;
88+
}
89+
7590
FlutterAdLoaderAd build() {
7691
if (manager == null) {
7792
throw new IllegalStateException("manager must be provided");
@@ -92,12 +107,35 @@ FlutterAdLoaderAd build() {
92107
} else {
93108
adLoaderAd = new FlutterAdLoaderAd(id, manager, adUnitId, request, adLoader);
94109
}
110+
111+
if (bannerParameters != null) {
112+
adLoaderAd.bannerParameters =
113+
bannerParameters.asBannerParameters(
114+
new FlutterAdManagerAdViewLoadedListener(adLoaderAd));
115+
}
116+
95117
return adLoaderAd;
96118
}
97119
}
98120

99121
enum AdLoaderAdType {
100122
UNKNOWN,
123+
BANNER,
124+
}
125+
126+
static class BannerParameters {
127+
@NonNull final OnAdManagerAdViewLoadedListener listener;
128+
@NonNull final AdSize[] adSizes;
129+
@Nullable final AdManagerAdViewOptions adManagerAdViewOptions;
130+
131+
BannerParameters(
132+
@NonNull OnAdManagerAdViewLoadedListener listener,
133+
@NonNull AdSize[] adSizes,
134+
@Nullable AdManagerAdViewOptions adManagerAdViewOptions) {
135+
this.listener = listener;
136+
this.adSizes = adSizes;
137+
this.adManagerAdViewOptions = adManagerAdViewOptions;
138+
}
101139
}
102140

103141
protected FlutterAdLoaderAd(
@@ -140,13 +178,14 @@ void load() {
140178
// Note we delegate loading the ad to FlutterAdLoader mainly for testing purposes.
141179
// As of 20.0.0 of GMA, mockito is unable to mock AdLoader.
142180
if (request != null) {
143-
adLoader.loadAdLoaderAd(adUnitId, adListener, request.asAdRequest(adUnitId));
181+
adLoader.loadAdLoaderAd(
182+
adUnitId, adListener, request.asAdRequest(adUnitId), bannerParameters);
144183
return;
145184
}
146185

147186
if (adManagerRequest != null) {
148187
adLoader.loadAdManagerAdLoaderAd(
149-
adUnitId, adListener, adManagerRequest.asAdManagerAdRequest(adUnitId));
188+
adUnitId, adListener, adManagerRequest.asAdManagerAdRequest(adUnitId), bannerParameters);
150189
return;
151190
}
152191

@@ -160,7 +199,10 @@ AdLoaderAdType getAdLoaderAdType() {
160199

161200
@Nullable
162201
FlutterAdSize getAdSize() {
163-
return null;
202+
if (view == null || !(view instanceof AdManagerAdView)) {
203+
return null;
204+
}
205+
return new FlutterAdSize(((AdManagerAdView) view).getAdSize());
164206
}
165207

166208
@Nullable
@@ -169,5 +211,32 @@ String getFormatId() {
169211
}
170212

171213
@Override
172-
void dispose() {}
214+
@Nullable
215+
public PlatformView getPlatformView() {
216+
if (view == null) {
217+
return null;
218+
}
219+
220+
return new FlutterPlatformView(view);
221+
}
222+
223+
@Override
224+
public void onAdManagerAdViewLoaded(@NonNull AdManagerAdView adView) {
225+
view = adView;
226+
type = AdLoaderAdType.BANNER;
227+
manager.onAdLoaded(adId, adView.getResponseInfo());
228+
}
229+
230+
@Override
231+
void dispose() {
232+
if (view == null) {
233+
return;
234+
}
235+
236+
if (view instanceof BaseAdView) {
237+
((BaseAdView) view).destroy();
238+
}
239+
240+
view = null;
241+
}
173242
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.c language governing permissions and
14+
// limitations under the License.
15+
16+
package io.flutter.plugins.googlemobileads;
17+
18+
import androidx.annotation.Nullable;
19+
import com.google.android.gms.ads.formats.AdManagerAdViewOptions;
20+
21+
/** A wrapper for {@link com.google.android.gms.ads.formats.AdManagerAdViewOptions}. */
22+
class FlutterAdManagerAdViewOptions {
23+
24+
@Nullable final Boolean manualImpressionsEnabled;
25+
26+
FlutterAdManagerAdViewOptions(@Nullable Boolean manualImpressionsEnabled) {
27+
this.manualImpressionsEnabled = manualImpressionsEnabled;
28+
}
29+
30+
AdManagerAdViewOptions asAdManagerAdViewOptions() {
31+
AdManagerAdViewOptions.Builder builder = new AdManagerAdViewOptions.Builder();
32+
if (manualImpressionsEnabled != null) {
33+
builder.setManualImpressionsEnabled(manualImpressionsEnabled);
34+
}
35+
return builder.build();
36+
}
37+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 20222 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package io.flutter.plugins.googlemobileads;
16+
17+
import androidx.annotation.NonNull;
18+
import androidx.annotation.Nullable;
19+
import com.google.android.gms.ads.AdSize;
20+
import com.google.android.gms.ads.formats.OnAdManagerAdViewLoadedListener;
21+
import java.util.List;
22+
23+
class FlutterBannerParameters {
24+
@NonNull final List<FlutterAdSize> sizes;
25+
@Nullable final FlutterAdManagerAdViewOptions adManagerAdViewOptions;
26+
27+
FlutterBannerParameters(
28+
@NonNull List<FlutterAdSize> sizes,
29+
@Nullable FlutterAdManagerAdViewOptions adManagerAdViewOptions) {
30+
this.sizes = sizes;
31+
this.adManagerAdViewOptions = adManagerAdViewOptions;
32+
}
33+
34+
FlutterAdLoaderAd.BannerParameters asBannerParameters(
35+
@NonNull OnAdManagerAdViewLoadedListener listener) {
36+
AdSize[] adSizes = new AdSize[sizes.size()];
37+
int i = 0;
38+
for (FlutterAdSize size : sizes) {
39+
adSizes[i++] = size.getAdSize();
40+
}
41+
return new FlutterAdLoaderAd.BannerParameters(
42+
listener,
43+
adSizes,
44+
adManagerAdViewOptions != null ? adManagerAdViewOptions.asAdManagerAdViewOptions() : null);
45+
}
46+
}

packages/google_mobile_ads/android/src/main/java/io/flutter/plugins/googlemobileads/GoogleMobileAdsPlugin.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ public void onAdInspectorClosed(@Nullable AdInspectorError adInspectorError) {
445445
adLoaderSupplier != null
446446
? adLoaderSupplier.get()
447447
: new FlutterAdLoader(context))
448+
.setBanner(call.<FlutterBannerParameters>argument("banner"))
448449
.build();
449450
instanceManager.trackAd(adLoaderAd, call.<Integer>argument("adId"));
450451
adLoaderAd.load();

0 commit comments

Comments
 (0)