Skip to content

Commit

Permalink
feat(ios)!: Google Mobile Ads SDK 8 w/new testDeviceIdentifiers vs te…
Browse files Browse the repository at this point in the history
…stDevices (#30)

* refactor: smart banner deprecation in favor of adaptive banner
* make banner ads work in v8
* refactor: interstitial ads implementation
* refactor: rewarded ads v8
* refactor: set testdevices for all ads, instead of per request
* docs: add test devices example
* lint(ios): `yarn lint:ios:fix`
* build(patch-package): remove spurious done from script
holdover from living in a monorepo where it was in a loop...

Co-authored-by: Mike Hardy <[email protected]>

BREAKING CHANGE: "testDevices" property no longer exists. You must use "testDeviceIdentifiers". The testDeviceIdentifiers property applies to all ad requests, while the old testDevices property was set per-request.
  • Loading branch information
dylancom authored Dec 11, 2021
1 parent 1a694ae commit bac264d
Show file tree
Hide file tree
Showing 16 changed files with 210 additions and 332 deletions.
1 change: 0 additions & 1 deletion .github/workflows/create_test_patches.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ jobs:
mv package react-native-google-ads
popd
npx patch-package $PACKAGE_NAME || true
done
ls -la $HOME/template/patches
shell: bash

Expand Down
3 changes: 3 additions & 0 deletions docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ admob()
// Indicates that you want the ad request to be handled in a
// manner suitable for users under the age of consent.
tagForUnderAgeOfConsent: true,

// An array of test device IDs to whitelist.
testDeviceIdentifiers: ["EMULATOR"];
})
.then(() => {
// Request config successfully set!
Expand Down
2 changes: 1 addition & 1 deletion ios/RNGoogleAds/RNGoogleAdsBannerViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ - (void)adViewDidReceiveAd:(GADBannerView *)adView {
}];
}

- (void)adView:(GADBannerView *)adView didFailToReceiveAdWithError:(GADRequestError *)error {
- (void)adView:(GADBannerView *)adView didFailToReceiveAdWithError:(NSError *)error {
NSDictionary *errorAndMessage = [RNGoogleAdsCommon getCodeAndMessageFromAdError:error];
[self sendEvent:@"onAdFailedToLoad" payload:errorAndMessage];
}
Expand Down
4 changes: 2 additions & 2 deletions ios/RNGoogleAds/RNGoogleAdsCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

+ (GADRequest *)buildAdRequest:(NSDictionary *)adRequestOptions;

+ (NSDictionary *)getCodeAndMessageFromAdError:(GADRequestError *)error;
+ (NSDictionary *)getCodeAndMessageFromAdError:(NSError *)error;

+ (void)sendAdEvent:(NSString *)event
requestId:(NSNumber *)requestId
Expand All @@ -36,7 +36,7 @@

@end

@interface RNGADInterstitial : GADInterstitial
@interface RNGADInterstitial : GADInterstitialAd
@property(nonatomic) NSNumber *requestId;
- (void)setRequestId:(NSNumber *)requestId;
@end
Expand Down
42 changes: 14 additions & 28 deletions ios/RNGoogleAds/RNGoogleAdsCommon.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
NSString *const GOOGLE_ADS_EVENT_REWARDED_LOADED = @"rewarded_loaded";
NSString *const GOOGLE_ADS_EVENT_REWARDED_EARNED_REWARD = @"rewarded_earned_reward";

@implementation RNGADInterstitial : GADInterstitial
@implementation RNGADInterstitial : GADInterstitialAd
- (void)setRequestId:(NSNumber *)requestId {
_requestId = requestId;
}
Expand Down Expand Up @@ -68,18 +68,6 @@ + (GADRequest *)buildAdRequest:(NSDictionary *)adRequestOptions {
request.keywords = adRequestOptions[@"keywords"];
}

if (adRequestOptions[@"testDevices"]) {
NSMutableArray *devices = [@[] mutableCopy];
for (NSString *key in adRequestOptions[@"testDevices"]) {
if ([key isEqualToString:@"EMULATOR"]) {
[devices addObject:kGADSimulatorID];
} else {
[devices addObject:key];
}
}
request.testDevices = devices;
}

if (adRequestOptions[@"location"]) {
NSArray<NSNumber *> *latLong = adRequestOptions[@"location"];
[request setLocationWithLatitude:[latLong[0] doubleValue]
Expand All @@ -98,20 +86,20 @@ + (GADRequest *)buildAdRequest:(NSDictionary *)adRequestOptions {
return request;
}

+ (NSDictionary *)getCodeAndMessageFromAdError:(GADRequestError *)error {
+ (NSDictionary *)getCodeAndMessageFromAdError:(NSError *)error {
NSString *code = @"unknown";
NSString *message = @"An unknown error occurred.";

if (error.code == kGADErrorInvalidRequest) {
if (error.code == GADErrorInvalidRequest) {
code = @"invalid-request";
message = @"The ad request was invalid; for instance, the ad unit ID was incorrect.";
} else if (error.code == kGADErrorNoFill) {
} else if (error.code == GADErrorNoFill) {
code = @"no-fill";
message = @"The ad request was successful, but no ad was returned due to lack of ad inventory.";
} else if (error.code == kGADErrorNetworkError) {
} else if (error.code == GADErrorNetworkError) {
code = @"network-error";
message = @"The ad request was unsuccessful due to network connectivity.";
} else if (error.code == kGADErrorInternalError) {
} else if (error.code == GADErrorInternalError) {
code = @"internal-error";
message = @"Something happened internally; for instance, an invalid response was received from "
@"the ad server.";
Expand Down Expand Up @@ -172,26 +160,24 @@ + (GADAdSize)stringToAdSize:(NSString *)value {
value = [value uppercaseString];

if ([value isEqualToString:@"BANNER"]) {
return kGADAdSizeBanner;
return GADAdSizeBanner;
} else if ([value isEqualToString:@"FLUID"]) {
return kGADAdSizeFluid;
return GADAdSizeFluid;
} else if ([value isEqualToString:@"WIDE_SKYSCRAPER"]) {
return kGADAdSizeSkyscraper;
return GADAdSizeSkyscraper;
} else if ([value isEqualToString:@"LARGE_BANNER"]) {
return kGADAdSizeLargeBanner;
return GADAdSizeLargeBanner;
} else if ([value isEqualToString:@"MEDIUM_RECTANGLE"]) {
return kGADAdSizeMediumRectangle;
return GADAdSizeMediumRectangle;
} else if ([value isEqualToString:@"FULL_BANNER"]) {
return kGADAdSizeFullBanner;
return GADAdSizeFullBanner;
} else if ([value isEqualToString:@"LEADERBOARD"]) {
return kGADAdSizeLeaderboard;
} else if ([value isEqualToString:@"SMART_BANNER"]) {
return kGADAdSizeSmartBannerPortrait;
return GADAdSizeLeaderboard;
} else if ([value isEqualToString:@"ADAPTIVE_BANNER"]) {
CGFloat viewWidth = [[UIScreen mainScreen] bounds].size.width;
return GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(viewWidth);
} else {
return kGADAdSizeBanner;
return GADAdSizeBanner;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,10 @@

#import "RNGoogleAdsCommon.h"

@interface RNGoogleAdsInterstitialDelegate : NSObject <GADInterstitialDelegate>
@interface RNGoogleAdsFullScreenContentDelegate : NSObject <GADFullScreenContentDelegate>

+ (_Nonnull instancetype)sharedInstance;
@property(nonatomic, copy) NSString *sendAdEvent;
@property(nonatomic, copy) NSNumber *requestId;
@property(nonatomic, copy) NSString *adUnitId;

+ (void)sendInterstitialEvent:(NSString *)type
requestId:(NSNumber *)requestId
adUnitId:(NSString *)adUnitId
error:(nullable NSDictionary *)error;

@end
@end
57 changes: 57 additions & 0 deletions ios/RNGoogleAds/RNGoogleAdsFullScreenContentDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#import "RNGoogleAdsFullScreenContentDelegate.h"

@implementation RNGoogleAdsFullScreenContentDelegate

#pragma mark -
#pragma mark GADFullScreenContentDelegate Methods

/// Tells the delegate that the ad presented full screen content.
- (void)adDidPresentFullScreenContent:(nonnull id<GADFullScreenPresentingAd>)ad {
[RNGoogleAdsCommon sendAdEvent:_sendAdEvent
requestId:_requestId
type:GOOGLE_ADS_EVENT_OPENED
adUnitId:_adUnitId
error:nil
data:nil];
}

/// Tells the delegate that the ad failed to present full screen content.
- (void)ad:(nonnull id<GADFullScreenPresentingAd>)ad
didFailToPresentFullScreenContentWithError:(nonnull NSError *)error {
NSDictionary *codeAndMessage = [RNGoogleAdsCommon getCodeAndMessageFromAdError:error];
[RNGoogleAdsCommon sendAdEvent:_sendAdEvent
requestId:_requestId
type:GOOGLE_ADS_EVENT_ERROR
adUnitId:_adUnitId
error:codeAndMessage
data:nil];
}

/// Tells the delegate that the ad dismissed full screen content.
- (void)adDidDismissFullScreenContent:(nonnull id<GADFullScreenPresentingAd>)ad {
[RNGoogleAdsCommon sendAdEvent:_sendAdEvent
requestId:_requestId
type:GOOGLE_ADS_EVENT_CLOSED
adUnitId:_adUnitId
error:nil
data:nil];
}

@end
89 changes: 0 additions & 89 deletions ios/RNGoogleAds/RNGoogleAdsInterstitialDelegate.m

This file was deleted.

47 changes: 37 additions & 10 deletions ios/RNGoogleAds/RNGoogleAdsInterstitialModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
#import <React/RCTUtils.h>

#import "RNGoogleAdsCommon.h"
#import "RNGoogleAdsInterstitialDelegate.h"
#import "RNGoogleAdsFullScreenContentDelegate.h"
#import "RNGoogleAdsInterstitialModule.h"
#import "common/RNSharedUtils.h"

static __strong NSMutableDictionary *interstitialMap;
static __strong NSMutableDictionary *interstitialDelegateMap;

@implementation RNGoogleAdsInterstitialModule
#pragma mark -
Expand All @@ -40,6 +41,7 @@ - (id)init {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
interstitialMap = [[NSMutableDictionary alloc] init];
interstitialDelegateMap = [[NSMutableDictionary alloc] init];
});
return self;
}
Expand All @@ -54,9 +56,8 @@ - (void)dealloc {

- (void)invalidate {
for (NSNumber *id in [interstitialMap allKeys]) {
RNGADInterstitial *ad = interstitialMap[id];
[ad setRequestId:@-1];
[interstitialMap removeObjectForKey:id];
[interstitialDelegateMap removeObjectForKey:id];
}
}

Expand All @@ -67,20 +68,46 @@ - (void)invalidate {
: (nonnull NSNumber *)requestId
: (NSString *)adUnitId
: (NSDictionary *)adRequestOptions) {
RNGADInterstitial *interstitial = [[RNGADInterstitial alloc] initWithAdUnitID:adUnitId];
[interstitial setRequestId:requestId];
[interstitial loadRequest:[RNGoogleAdsCommon buildAdRequest:adRequestOptions]];
interstitial.delegate = [RNGoogleAdsInterstitialDelegate sharedInstance];
interstitialMap[requestId] = interstitial;
GADRequest *request = [GADRequest request];
[GADInterstitialAd loadWithAdUnitID:adUnitId
request:request
completionHandler:^(GADInterstitialAd *ad, NSError *error) {
if (error) {
NSDictionary *codeAndMessage =
[RNGoogleAdsCommon getCodeAndMessageFromAdError:error];
[RNGoogleAdsCommon sendAdEvent:GOOGLE_ADS_EVENT_INTERSTITIAL
requestId:requestId
type:GOOGLE_ADS_EVENT_ERROR
adUnitId:ad.adUnitID
error:codeAndMessage
data:nil];
return;
}
GADInterstitialAd *interstitial = ad;
RNGoogleAdsFullScreenContentDelegate *fullScreenContentDelegate =
[[RNGoogleAdsFullScreenContentDelegate alloc] init];
fullScreenContentDelegate.sendAdEvent = GOOGLE_ADS_EVENT_INTERSTITIAL;
fullScreenContentDelegate.requestId = requestId;
fullScreenContentDelegate.adUnitId = ad.adUnitID;
interstitial.fullScreenContentDelegate = fullScreenContentDelegate;
interstitialMap[requestId] = interstitial;
interstitialDelegateMap[requestId] = fullScreenContentDelegate;
[RNGoogleAdsCommon sendAdEvent:GOOGLE_ADS_EVENT_INTERSTITIAL
requestId:requestId
type:GOOGLE_ADS_EVENT_LOADED
adUnitId:ad.adUnitID
error:nil
data:nil];
}];
}

RCT_EXPORT_METHOD(interstitialShow
: (nonnull NSNumber *)requestId
: (NSDictionary *)showOptions
: (RCTPromiseResolveBlock)resolve
: (RCTPromiseRejectBlock)reject) {
GADInterstitial *interstitial = interstitialMap[requestId];
if (interstitial.isReady) {
GADInterstitialAd *interstitial = interstitialMap[requestId];
if (interstitial) {
[interstitial
presentFromRootViewController:RCTSharedApplication().delegate.window.rootViewController];
resolve([NSNull null]);
Expand Down
Loading

0 comments on commit bac264d

Please sign in to comment.