Skip to content

Commit

Permalink
Add support for current orientation in AnchoredAdaptiveBannerAdSize (g…
Browse files Browse the repository at this point in the history
…oogleads#397)

* Add support for current orientation AdSize in AnchoredAdaptiveBannerAdSize

Implement AnchoredAdaptiveBannerAdSize API for current orientation  and Test along with portrait and landscape.

* Update build.gradle

update androidx test core version

* Add Encode Decode tests for AnchoredAdaptiveBannerAdSize in AdMessageCodecTest and Resolve comments

* Flutter format

Remove unused import

* Update codec in encodeAnchoredAdaptiveBannerAdSize Test

* Update AdMessageCodecTest.java

* Update build.gradle and few minor changes to AnchoredAdaptiveBannerAdSize

Add @nullable for orientation and update Error text for wrong `orientation` value.
  • Loading branch information
srichakradhar authored Oct 8, 2021
1 parent f32f2e8 commit f901a11
Show file tree
Hide file tree
Showing 15 changed files with 302 additions and 29 deletions.
7 changes: 7 additions & 0 deletions packages/google_mobile_ads/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
You can see the [fluid_example.dart](https://github.com/googleads/googleads-mobile-flutter/blob/master/packages/google_mobile_ads/example/lib/fluid_example.dart) for a reference of how to load and display a fluid ad.
* Android - https://developers.google.com/ad-manager/mobile-ads-sdk/android/native/styles#fluid_size
* iOS - https://developers.google.com/ad-manager/mobile-ads-sdk/ios/native/native-styles#fluid_size
* Adds `AdSize. getCurrentOrientationAnchoredAdaptiveBannerAdSize()` to support getting an `AnchoredAdaptiveBannerAdSize` in the current orientation.
* Previously the user had to specify an orientation (portrait / landscape) to create an AnchoredAdaptiveBannerAdSize. It has been made optional with this version. SDK will determine the current orientation of the device and return an appropriate AdSize.
* More information on anchored adaptive banners can be found here:
* [Admob android](https://developers.google.com/admob/android/banner/anchored-adaptive)
* [Admob iOS](https://developers.google.com/admob/ios/banner/anchored-adaptive)
* [Ad manager android](https://developers.google.com/ad-manager/mobile-ads-sdk/android/banner/anchored-adaptive)
* [Ad manager iOS](https://developers.google.com/ad-manager/mobile-ads-sdk/ios/banner/anchored-adaptive)
* Adds support for inline adaptive banner ads.
* Inline adaptive banner ads are meant to be used in scrollable content. They are of variable height and can be as tall as the device screen.
They differ from Fluid ads in that they only resize once when the ad is loaded.
Expand Down
3 changes: 2 additions & 1 deletion packages/google_mobile_ads/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ android {
testImplementation 'org.hamcrest:hamcrest:2.2'
testImplementation 'org.mockito:mockito-inline:3.9.0'
testImplementation 'org.robolectric:robolectric:4.4'
testImplementation 'androidx.test:core:1.3.0'
}
testOptions {
unitTests {
Expand Down Expand Up @@ -67,4 +68,4 @@ afterEvaluate {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ AdSize getLandscapeAnchoredAdaptiveBannerAdSize(Context context, int width) {
return AdSize.getLandscapeAnchoredAdaptiveBannerAdSize(context, width);
}

AdSize getCurrentOrientationAnchoredAdaptiveBannerAdSize(Context context, int width) {
return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, width);
}

AdSize getCurrentOrientationInlineAdaptiveBannerAdSize(Context context, int width) {
return AdSize.getCurrentOrientationInlineAdaptiveBannerAdSize(context, width);
}
Expand All @@ -59,24 +63,25 @@ static class AnchoredAdaptiveBannerAdSize extends FlutterAdSize {
private static AdSize getAdSize(
@NonNull Context context,
@NonNull AdSizeFactory factory,
@NonNull String orientation,
@Nullable String orientation,
int width) {
final AdSize adSize;
if (orientation.equals("portrait")) {
if (orientation == null) {
adSize = factory.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, width);
} else if (orientation.equals("portrait")) {
adSize = factory.getPortraitAnchoredAdaptiveBannerAdSize(context, width);
} else if (orientation.equals("landscape")) {
adSize = factory.getLandscapeAnchoredAdaptiveBannerAdSize(context, width);
} else {
throw new IllegalArgumentException(
"Orientation should be 'portrait' or 'landscape': " + orientation);
throw new IllegalArgumentException("Unexpected value for orientation: " + orientation);
}
return adSize;
}

AnchoredAdaptiveBannerAdSize(
@NonNull Context context,
@NonNull AdSizeFactory factory,
@NonNull String orientation,
@Nullable String orientation,
int width) {
super(getAdSize(context, factory, orientation, width));
this.orientation = orientation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result)
case "AdSize#getAnchoredAdaptiveBannerAdSize":
final FlutterAdSize.AnchoredAdaptiveBannerAdSize size =
new FlutterAdSize.AnchoredAdaptiveBannerAdSize(
activityBinding.getActivity(),
appContext,
new FlutterAdSize.AdSizeFactory(),
call.<String>argument("orientation"),
call.<Integer>argument("width"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,33 @@ public void encodeAnchoredAdaptiveBannerAdSize() {
.when(mockAdSizeFactory)
.getPortraitAnchoredAdaptiveBannerAdSize(any(Context.class), anyInt());

final AnchoredAdaptiveBannerAdSize adaptiveAdSize =
doReturn(mockAdSize)
.when(mockAdSizeFactory)
.getLandscapeAnchoredAdaptiveBannerAdSize(any(Context.class), anyInt());

doReturn(mockAdSize)
.when(mockAdSizeFactory)
.getCurrentOrientationAnchoredAdaptiveBannerAdSize(any(Context.class), anyInt());

final AnchoredAdaptiveBannerAdSize portraitAnchoredAdaptiveAdSize =
new AnchoredAdaptiveBannerAdSize(mock(Context.class), mockAdSizeFactory, "portrait", 23);
final ByteBuffer data = codec.encodeMessage(adaptiveAdSize);
final ByteBuffer portraitData = codec.encodeMessage(portraitAnchoredAdaptiveAdSize);

final AnchoredAdaptiveBannerAdSize portraitResult =
(AnchoredAdaptiveBannerAdSize) codec.decodeMessage((ByteBuffer) portraitData.position(0));
assertEquals(portraitResult.size, mockAdSize);

final AnchoredAdaptiveBannerAdSize landscapeAnchoredAdaptiveAdSize =
new AnchoredAdaptiveBannerAdSize(mock(Context.class), mockAdSizeFactory, "landscape", 34);
final ByteBuffer landscapeData = codec.encodeMessage(landscapeAnchoredAdaptiveAdSize);

final AnchoredAdaptiveBannerAdSize landscapeResult =
(AnchoredAdaptiveBannerAdSize) codec.decodeMessage((ByteBuffer) landscapeData.position(0));
assertEquals(landscapeResult.size, mockAdSize);

final AnchoredAdaptiveBannerAdSize anchoredAdaptiveAdSize =
new AnchoredAdaptiveBannerAdSize(mock(Context.class), mockAdSizeFactory, null, 45);
final ByteBuffer data = codec.encodeMessage(anchoredAdaptiveAdSize);

final AnchoredAdaptiveBannerAdSize result =
(AnchoredAdaptiveBannerAdSize) codec.decodeMessage((ByteBuffer) data.position(0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import androidx.test.core.app.ApplicationProvider;
import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
Expand All @@ -46,6 +47,7 @@
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.StandardMethodCodec;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.plugins.googlemobileads.FlutterAd.FlutterResponseInfo;
import java.nio.ByteBuffer;
import java.util.ArrayList;
Expand Down Expand Up @@ -600,6 +602,61 @@ public void testGetVersionString() {
}

@Test
public void testGetAnchoredAdaptiveBannerAdSize() {
// Setup mocks
AdInstanceManager testManagerSpy = spy(testManager);
FlutterMobileAdsWrapper mockMobileAds = mock(FlutterMobileAdsWrapper.class);
GoogleMobileAdsPlugin plugin =
new GoogleMobileAdsPlugin(mockFlutterPluginBinding, testManagerSpy, mockMobileAds);

BinaryMessenger mockBinaryMessenger = mock(BinaryMessenger.class);
FlutterPluginBinding mockActivityPluginBinding = mock(FlutterPluginBinding.class);
PlatformViewRegistry mockPlatformViewRegistry = mock(PlatformViewRegistry.class);

Context context = ApplicationProvider.getApplicationContext();

doReturn(context).when(mockActivityPluginBinding).getApplicationContext();
doReturn(mockBinaryMessenger).when(mockActivityPluginBinding).getBinaryMessenger();
doReturn(mockPlatformViewRegistry).when(mockActivityPluginBinding).getPlatformViewRegistry();

plugin.onAttachedToEngine(mockActivityPluginBinding);

// Test for portrait Banner AdSize.
HashMap<String, Object> arguments = new HashMap<>();
arguments.put("orientation", "portrait");
arguments.put("width", 23);

AdSize adSize = AdSize.getPortraitAnchoredAdaptiveBannerAdSize(context, 23);
MethodCall methodCall = new MethodCall("AdSize#getAnchoredAdaptiveBannerAdSize", arguments);
Result result = mock(Result.class);
plugin.onMethodCall(methodCall, result);

verify(result).success(adSize.getHeight());

// Test for landscape Banner AdSize.
arguments = new HashMap<>();
arguments.put("orientation", "landscape");
arguments.put("width", 23);

adSize = AdSize.getLandscapeAnchoredAdaptiveBannerAdSize(context, 23);
methodCall = new MethodCall("AdSize#getAnchoredAdaptiveBannerAdSize", arguments);
result = mock(Result.class);
plugin.onMethodCall(methodCall, result);

verify(result).success(adSize.getHeight());

// Test for current orientation (inferred) Banner AdSize.
arguments = new HashMap<>();
arguments.put("width", 23);

adSize = AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, 23);
methodCall = new MethodCall("AdSize#getAnchoredAdaptiveBannerAdSize", arguments);
result = mock(Result.class);
plugin.onMethodCall(methodCall, result);

verify(result).success(adSize.getHeight());
}

public void testGetAdSize_bannerAd() {
// Setup mocks
AdInstanceManager testManagerSpy = spy(testManager);
Expand Down
6 changes: 2 additions & 4 deletions packages/google_mobile_ads/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,8 @@ class _MyAppState extends State<MyApp> {

Future<void> _createAnchoredBanner(BuildContext context) async {
final AnchoredAdaptiveBannerAdSize? size =
await AdSize.getAnchoredAdaptiveBannerAdSize(
Orientation.portrait,
MediaQuery.of(context).size.width.truncate(),
);
await AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(
MediaQuery.of(context).size.width.truncate());

if (size == null) {
print('Unable to get height of anchored banner.');
Expand Down
1 change: 1 addition & 0 deletions packages/google_mobile_ads/ios/Classes/FLTAd_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
@interface FLTAdSizeFactory : NSObject
- (GADAdSize)portraitAnchoredAdaptiveBannerAdSizeWithWidth:(NSNumber *_Nonnull)width;
- (GADAdSize)landscapeAnchoredAdaptiveBannerAdSizeWithWidth:(NSNumber *_Nonnull)width;
- (GADAdSize)currentOrientationAnchoredAdaptiveBannerAdSizeWithWidth:(NSNumber *_Nonnull)width;
- (GADAdSize)currentOrientationInlineAdaptiveBannerSizeWithWidth:(NSNumber *_Nonnull)width;
- (GADAdSize)portraitOrientationInlineAdaptiveBannerSizeWithWidth:(NSNumber *_Nonnull)width;
- (GADAdSize)landscapeInlineAdaptiveBannerAdSizeWithWidth:(NSNumber *_Nonnull)width;
Expand Down
12 changes: 9 additions & 3 deletions packages/google_mobile_ads/ios/Classes/FLTAd_Internal.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ - (GADAdSize)landscapeAnchoredAdaptiveBannerAdSizeWithWidth:(NSNumber *_Nonnull)
return GADLandscapeAnchoredAdaptiveBannerAdSizeWithWidth(width.doubleValue);
}

- (GADAdSize)currentOrientationAnchoredAdaptiveBannerAdSizeWithWidth:(NSNumber *_Nonnull)width {
return GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(width.doubleValue);
}

- (GADAdSize)currentOrientationInlineAdaptiveBannerSizeWithWidth:(NSNumber *_Nonnull)width {
return GADCurrentOrientationInlineAdaptiveBannerAdSizeWithWidth(width.floatValue);
}
Expand All @@ -61,15 +65,17 @@ - (GADAdSize)inlineAdaptiveBannerAdSizeWithWidthAndMaxHeight:(NSNumber *_Nonnull

@implementation FLTAnchoredAdaptiveBannerSize
- (instancetype _Nonnull)initWithFactory:(FLTAdSizeFactory *_Nonnull)factory
orientation:(NSString *_Nonnull)orientation
orientation:(NSString *)orientation
width:(NSNumber *_Nonnull)width {
GADAdSize size;
if ([orientation isEqualToString:@"portrait"]) {
if ([FLTAdUtil isNull:orientation]) {
size = [factory currentOrientationAnchoredAdaptiveBannerAdSizeWithWidth:width];
} else if ([orientation isEqualToString:@"portrait"]) {
size = [factory portraitAnchoredAdaptiveBannerAdSizeWithWidth:width];
} else if ([orientation isEqualToString:@"landscape"]) {
size = [factory landscapeAnchoredAdaptiveBannerAdSizeWithWidth:width];
} else {
NSLog(@"AdaptiveBanner orientation should be 'portrait' or 'landscape': %@", orientation);
NSLog(@"Unexpected value for orientation: %@", orientation);
return nil;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,63 @@ - (void)testGetVersionString {
XCTAssertEqual(returnedResult, [GADMobileAds.sharedInstance sdkVersion]);
}

- (void)testGetAnchoredAdaptiveBannerAdSize {
FlutterMethodCall *methodCall =
[FlutterMethodCall methodCallWithMethodName:@"AdSize#getAnchoredAdaptiveBannerAdSize"
arguments:@{
@"orientation" : @"portrait",
@"width" : @23,
}];

__block bool resultInvoked = false;
__block id _Nullable returnedResult;
FlutterResult result = ^(id _Nullable result) {
resultInvoked = true;
returnedResult = result;
};

[_fltGoogleMobileAdsPlugin handleMethodCall:methodCall result:result];

XCTAssertTrue(resultInvoked);
XCTAssertEqual([returnedResult doubleValue],
GADPortraitAnchoredAdaptiveBannerAdSizeWithWidth(23).size.height);

methodCall = [FlutterMethodCall methodCallWithMethodName:@"AdSize#getAnchoredAdaptiveBannerAdSize"
arguments:@{
@"orientation" : @"landscape",
@"width" : @34,
}];

resultInvoked = false;
result = ^(id _Nullable result) {
resultInvoked = true;
returnedResult = result;
};

[_fltGoogleMobileAdsPlugin handleMethodCall:methodCall result:result];

XCTAssertTrue(resultInvoked);
XCTAssertEqual([returnedResult doubleValue],
GADLandscapeAnchoredAdaptiveBannerAdSizeWithWidth(34).size.height);

methodCall = [FlutterMethodCall methodCallWithMethodName:@"AdSize#getAnchoredAdaptiveBannerAdSize"
arguments:@{
@"width" : @45,
}];

resultInvoked = false;
result = ^(id _Nullable result) {
resultInvoked = true;
returnedResult = result;
};

[_fltGoogleMobileAdsPlugin handleMethodCall:methodCall result:result];

XCTAssertTrue(resultInvoked);
XCTAssertEqual([returnedResult doubleValue],
GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(45).size.height);
}

- (void)testGetAdSize_bannerAd {
// Method calls to load a banner ad.
FlutterMethodCall *loadAdMethodCall =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ - (void)testEncodeDecodeInlineAdaptiveBannerAdSize_withMaxHeight {
XCTAssertEqualObjects(decodedSize.orientation, inlineAdaptiveBannerSize.orientation);
}

- (void)testEncodeDecodeAnchoredAdaptiveBannerAdSize {
GADAdSize testAdSize = GADAdSizeFromCGSize(CGSizeMake(0, 0));
- (void)testEncodeDecodeAnchoredAdaptiveBannerAdSize_portraitOrientation {
GADAdSize testAdSize = GADAdSizeFromCGSize(CGSizeMake(23, 34));

FLTAdSizeFactory *factory = OCMClassMock([FLTAdSizeFactory class]);
OCMStub([factory portraitAnchoredAdaptiveBannerAdSizeWithWidth:@(23)]).andReturn(testAdSize);
Expand All @@ -148,6 +148,37 @@ - (void)testEncodeDecodeAnchoredAdaptiveBannerAdSize {
XCTAssertEqual(decodedSize.size.size.width, testAdSize.size.width);
}

- (void)testEncodeDecodeAnchoredAdaptiveBannerAdSize_landscapeOrientation {
GADAdSize testAdSize = GADAdSizeFromCGSize(CGSizeMake(34, 45));

FLTAdSizeFactory *factory = OCMClassMock([FLTAdSizeFactory class]);
OCMStub([factory landscapeAnchoredAdaptiveBannerAdSizeWithWidth:@(34)]).andReturn(testAdSize);

FLTAnchoredAdaptiveBannerSize *size =
[[FLTAnchoredAdaptiveBannerSize alloc] initWithFactory:factory
orientation:@"landscape"
width:@(34)];
NSData *encodedMessage = [_messageCodec encode:size];

FLTAnchoredAdaptiveBannerSize *decodedSize = [_messageCodec decode:encodedMessage];
XCTAssertEqual(decodedSize.size.size.width, testAdSize.size.width);
}

- (void)testEncodeDecodeAnchoredAdaptiveBannerAdSize_currentOrientation {
GADAdSize testAdSize = GADAdSizeFromCGSize(CGSizeMake(45, 56));

FLTAdSizeFactory *factory = OCMClassMock([FLTAdSizeFactory class]);
OCMStub([factory currentOrientationAnchoredAdaptiveBannerAdSizeWithWidth:@(45)])
.andReturn(testAdSize);

FLTAnchoredAdaptiveBannerSize *size =
[[FLTAnchoredAdaptiveBannerSize alloc] initWithFactory:factory orientation:NULL width:@(45)];
NSData *encodedMessage = [_messageCodec encode:size];

FLTAnchoredAdaptiveBannerSize *decodedSize = [_messageCodec decode:encodedMessage];
XCTAssertEqual(decodedSize.size.size.width, testAdSize.size.width);
}

- (void)testEncodeDecodeSmartBannerAdSize {
FLTSmartBannerSize *size = [[FLTSmartBannerSize alloc] initWithOrientation:@"landscape"];

Expand Down Expand Up @@ -440,4 +471,8 @@ - (GADAdSize)portraitAnchoredAdaptiveBannerAdSizeWithWidth:(NSNumber *)width {
- (GADAdSize)landscapeAnchoredAdaptiveBannerAdSizeWithWidth:(NSNumber *)width {
return GADAdSizeFromCGSize(CGSizeMake(width.doubleValue, 0));
}

- (GADAdSize)currentOrientationAnchoredAdaptiveBannerAdSizeWithWidth:(NSNumber *)width {
return GADAdSizeFromCGSize(CGSizeMake(width.doubleValue, 0));
}
@end
Loading

0 comments on commit f901a11

Please sign in to comment.