diff --git a/README.md b/README.md index 452944b7..73ca84d6 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ When using The New Architecture, some legacy code will still be used though. See | -------- | ------------------------------------------------- | ----------- | | iOS | Mobile Ads SDK Methods (Turbo Native Module) | ✅ Complete | | iOS | Banners (Fabric Native Component) | ✅ Complete | -| iOS | Full Screen Ads (Turbo Native Module) | ⏳ To-Do | +| iOS | Full Screen Ads (Turbo Native Module) | ✅ Complete | | iOS | User Messaging Platform (Turbo Native Module) | ⏳ To-Do | | iOS | EventEmitter (Turbo Native Module) | ⏳ To-Do | | iOS | Revenue Precision Constants (Turbo Native Module) | ⏳ To-Do | diff --git a/__tests__/googleMobileAds.test.ts b/__tests__/googleMobileAds.test.ts index 12189f12..90aadcae 100644 --- a/__tests__/googleMobileAds.test.ts +++ b/__tests__/googleMobileAds.test.ts @@ -1,5 +1,5 @@ import admob, { MaxAdContentRating } from '../src'; -import RNGoogleMobileAdsModule from '../src/NativeGoogleMobileAdsModule'; +import RNGoogleMobileAdsModule from '../src/specs/modules/NativeGoogleMobileAdsModule'; describe('Admob', function () { describe('setRequestConfiguration()', function () { diff --git a/__tests__/interstitial.test.ts b/__tests__/interstitial.test.ts index a869ddca..91cc5bd6 100644 --- a/__tests__/interstitial.test.ts +++ b/__tests__/interstitial.test.ts @@ -1,5 +1,5 @@ import { AdEventType, InterstitialAd } from '../src'; -import { NativeModules } from 'react-native'; +import NativeInterstitialModule from '../src/specs/modules/NativeInterstitialModule'; describe('Google Mobile Ads Interstitial', function () { describe('createForAdRequest', function () { @@ -34,23 +34,17 @@ describe('Google Mobile Ads Interstitial', function () { const ad = InterstitialAd.createForAdRequest('abc'); ad.load(); - expect(NativeModules.RNGoogleMobileAdsInterstitialModule.interstitialLoad).toBeCalledTimes( - 1, - ); + expect(NativeInterstitialModule.interstitialLoad).toBeCalledTimes(1); }); it('does nothing if ad currently loading', () => { const ad = InterstitialAd.createForAdRequest('abc'); ad.load(); - expect(NativeModules.RNGoogleMobileAdsInterstitialModule.interstitialLoad).toBeCalledTimes( - 1, - ); + expect(NativeInterstitialModule.interstitialLoad).toBeCalledTimes(1); ad.load(); - expect(NativeModules.RNGoogleMobileAdsInterstitialModule.interstitialLoad).toBeCalledTimes( - 1, - ); + expect(NativeInterstitialModule.interstitialLoad).toBeCalledTimes(1); }); it('does nothing if ad is already loaded', () => { @@ -60,41 +54,33 @@ describe('Google Mobile Ads Interstitial', function () { ad._handleAdEvent({ body: { type: AdEventType.LOADED } }); ad.load(); - expect(NativeModules.RNGoogleMobileAdsInterstitialModule.interstitialLoad).not.toBeCalled(); + expect(NativeInterstitialModule.interstitialLoad).not.toBeCalled(); }); it('can be called again after ad was closed', () => { const ad = InterstitialAd.createForAdRequest('abc'); ad.load(); - expect(NativeModules.RNGoogleMobileAdsInterstitialModule.interstitialLoad).toBeCalledTimes( - 1, - ); + expect(NativeInterstitialModule.interstitialLoad).toBeCalledTimes(1); // @ts-ignore ad._handleAdEvent({ body: { type: AdEventType.CLOSED } }); ad.load(); - expect(NativeModules.RNGoogleMobileAdsInterstitialModule.interstitialLoad).toBeCalledTimes( - 2, - ); + expect(NativeInterstitialModule.interstitialLoad).toBeCalledTimes(2); }); it('can be called again after ad failed to load', () => { const ad = InterstitialAd.createForAdRequest('abc'); ad.load(); - expect(NativeModules.RNGoogleMobileAdsInterstitialModule.interstitialLoad).toBeCalledTimes( - 1, - ); + expect(NativeInterstitialModule.interstitialLoad).toBeCalledTimes(1); // @ts-ignore ad._handleAdEvent({ body: { type: AdEventType.ERROR } }); ad.load(); - expect(NativeModules.RNGoogleMobileAdsInterstitialModule.interstitialLoad).toBeCalledTimes( - 2, - ); + expect(NativeInterstitialModule.interstitialLoad).toBeCalledTimes(2); }); }); diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.h b/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.h new file mode 100644 index 00000000..e1bd940d --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.h @@ -0,0 +1,36 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import + +#ifdef RCT_NEW_ARCH_ENABLED + +#import +@interface RNGoogleMobileAdsAppOpenModule : NSObject + +#else + +#import +@interface RNGoogleMobileAdsAppOpenModule : NSObject + +#endif + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.m b/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.m deleted file mode 100644 index 2ee8f82d..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.m +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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. - * - */ - -#if !TARGET_OS_MACCATALYST - -#import - -@interface RCT_EXTERN_MODULE (RNGoogleMobileAdsAppOpenModule, NSObject) - -- (dispatch_queue_t)methodQueue { - return dispatch_get_main_queue(); -} - -+ (BOOL)requiresMainQueueSetup { - return YES; -} - -RCT_EXTERN_METHOD(appOpenLoad - : (nonnull NSNumber *)requestId forAdUnitId - : (nonnull NSString *)adUnitId withAdRequestOptions - : (nonnull NSDictionary *)adRequestOptions) - -RCT_EXTERN_METHOD(appOpenShow - : (nonnull NSNumber *)requestId forAdUnitId - : (nonnull NSString *)adUnitId withShowOptions - : (NSDictionary *)showOptions withResolve - : (RCTPromiseResolveBlock)resolve withReject - : (RCTPromiseRejectBlock)reject) - -@end - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.mm b/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.mm new file mode 100644 index 00000000..0fe36bae --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.mm @@ -0,0 +1,100 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import "RNGoogleMobileAdsAppOpenModule.h" +#import +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNGoogleMobileAdsSpec.h" +#endif +#import "RNGoogleMobileAdsCommon.h" +#import "RNGoogleMobileAdsFullScreenAd.h" + +@interface RNGoogleMobileAdsAppOpenAd : RNGoogleMobileAdsFullScreenAd + +@end + +@implementation RNGoogleMobileAdsAppOpenAd + +- (NSString *)getAdEventName { + return GOOGLE_MOBILE_ADS_EVENT_APP_OPEN; +} + +- (void)loadAd:(NSString *)adUnitId + adRequest:(GAMRequest *)adRequest + completionHandler: + (void (^)(GADAppOpenAd *_Nullable ad, NSError *_Nullable error))completionHandler { + [GADAppOpenAd loadWithAdUnitID:adUnitId request:adRequest completionHandler:completionHandler]; +} + +@end + +@implementation RNGoogleMobileAdsAppOpenModule { + RNGoogleMobileAdsAppOpenAd *_ad; +} + +RCT_EXPORT_MODULE(); + +- (dispatch_queue_t)methodQueue { + return dispatch_get_main_queue(); +} + +RCT_EXPORT_METHOD(appOpenLoad + : (double)requestId adUnitId + : (NSString *)adUnitId requestOptions + : (NSDictionary *)requestOptions) { + [_ad loadWithRequestId:requestId adUnitId:adUnitId adRequestOptions:requestOptions]; +} + +RCT_EXPORT_METHOD(appOpenShow + : (double)requestId adUnitId + : (NSString *)adUnitId showOptions + : (NSDictionary *)showOptions resolve + : (RCTPromiseResolveBlock)resolve reject + : (RCTPromiseRejectBlock)reject) { + [_ad showWithRequestId:requestId + adUnitId:adUnitId + showOptions:showOptions + resolve:resolve + reject:reject]; +} + +RCT_EXPORT_METHOD(invalidate) { [_ad invalidate]; } + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params { + return std::make_shared(params); +} +#endif + +- (instancetype)init { + self = [super init]; + if (self) { + _ad = [[RNGoogleMobileAdsAppOpenAd alloc] init]; + } + return self; +} + +- (void)dealloc { + [self invalidate]; +} + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.swift b/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.swift deleted file mode 100644 index a121b105..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.swift +++ /dev/null @@ -1,85 +0,0 @@ -/** - * 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. - * - */ - -#if !targetEnvironment(macCatalyst) - -import Foundation -import GoogleMobileAds - -@objc(RNGoogleMobileAdsAppOpenModule) -class RNGoogleMobileAdsAppOpenModule: NSObject { - let ad = RNGoogleMobileAdsAppOpenAd() - - deinit { - invalidate() - } - - @objc - func invalidate() { - ad.invalidate() - } - - @objc(appOpenLoad:forAdUnitId:withAdRequestOptions:) - func appOpenLoad( - requestId: NSNumber, - adUnitId: String, - adRequestOptions: Dictionary - ) { - ad.load( - requestId: requestId.intValue, - adUnitId: adUnitId, - adRequestOptions: adRequestOptions - ) - } - - @objc(appOpenShow:forAdUnitId:withShowOptions:withResolve:withReject:) - func appOpenShow( - requestId: NSNumber, - adUnitId: String, - showOptions: Dictionary, - resolve: RCTPromiseResolveBlock?, - reject: RCTPromiseRejectBlock? - ) { - ad.show( - requestId: requestId.intValue, - adUnitId: adUnitId, - showOptions: showOptions, - resolve: resolve, - reject: reject - ) - } - - class RNGoogleMobileAdsAppOpenAd: RNGoogleMobileAdsFullScreenAd { - override func getAdEventName() -> String { - return GOOGLE_MOBILE_ADS_EVENT_APP_OPEN - } - - override func loadAd( - adUnitId: String, - adRequest: GAMRequest, - completionHandler: @escaping (GADAppOpenAd?, Error?) -> () - ) { - GADAppOpenAd.load( - withAdUnitID: adUnitId, - request: adRequest, - completionHandler: completionHandler - ) - } - } -} - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerView.h b/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerView.h index a8c55b8c..f7af510c 100644 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerView.h +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerView.h @@ -1,3 +1,5 @@ +#if !TARGET_OS_MACCATALYST + // This guard prevent this file to be compiled in the old architecture. #ifdef RCT_NEW_ARCH_ENABLED #import @@ -28,3 +30,5 @@ NS_ASSUME_NONNULL_END #endif /* NativeComponentExampleComponentView_h */ #endif /* RCT_NEW_ARCH_ENABLED */ + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerView.mm b/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerView.mm index 13ad4b48..b27d1f76 100644 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerView.mm +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerView.mm @@ -1,3 +1,5 @@ +#if !TARGET_OS_MACCATALYST + // This guard prevent the code from being compiled in the old architecture #ifdef RCT_NEW_ARCH_ENABLED #import "RNGoogleMobileAdsBannerView.h" @@ -236,11 +238,14 @@ - (void)adView:(nonnull GADBannerView *)banner } } +@end + #pragma mark - RNGoogleMobileAdsBannerViewCls Class RNGoogleMobileAdsBannerViewCls(void) { return RNGoogleMobileAdsBannerView.class; } -@end #endif + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsConsentModule.m b/ios/RNGoogleMobileAds/RNGoogleMobileAdsConsentModule.m index 047c8323..fb21793a 100644 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsConsentModule.m +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsConsentModule.m @@ -200,7 +200,9 @@ - (NSDictionary *)getConsentInformation { RCT_EXPORT_METHOD(getConsentInfo : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) { +#if !TARGET_OS_MACCATALYST resolve([self getConsentInformation]); +#endif } RCT_EXPORT_METHOD(getTCString : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) { diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.h b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.h new file mode 100644 index 00000000..055429b2 --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.h @@ -0,0 +1,53 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import +#import +#import "RNGoogleMobileAdsFullScreenContentDelegate.h" +#import "RNSharedUtils.h" + +@interface RNGoogleMobileAdsFullScreenAd : NSObject + +@property(nonatomic, strong) NSMutableDictionary> *adMap; +@property(nonatomic, strong) + NSMutableDictionary *delegateMap; + +- (instancetype)init; +- (void)invalidate; +- (NSString *)getAdEventName; +- (void)loadAd:(NSString *)adUnitId + adRequest:(GAMRequest *)adRequest + completionHandler:(void (^)(id ad, NSError *error))completionHandler; +- (void)sendAdEvent:(NSString *)type + requestId:(int)requestId + adUnitId:(NSString *)adUnitId + error:(NSDictionary *)error + data:(NSDictionary *)data; +- (void)loadWithRequestId:(int)requestId + adUnitId:(NSString *)adUnitId + adRequestOptions:(NSDictionary *)adRequestOptions; +- (void)showWithRequestId:(int)requestId + adUnitId:(NSString *)adUnitId + showOptions:(NSDictionary *)showOptions + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.mm b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.mm new file mode 100644 index 00000000..23741e70 --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.mm @@ -0,0 +1,220 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import "RNGoogleMobileAdsFullScreenAd.h" +#import "RNGoogleMobileAdsCommon.h" + +@implementation RNGoogleMobileAdsFullScreenAd + +- (instancetype)init { + if (self = [super init]) { + _adMap = [NSMutableDictionary new]; + _delegateMap = [NSMutableDictionary new]; + } + return self; +} + +- (void)dealloc { + [self invalidate]; +} + +- (void)invalidate { + [_adMap removeAllObjects]; + [_delegateMap removeAllObjects]; +} + +- (NSString *)getAdEventName { + @throw [NSException exceptionWithName:@"MethodNotImplemented" + reason:@"Method `getAdEventName` must be overridden" + userInfo:nil]; +} + +- (void)loadAd:(NSString *)adUnitId + adRequest:(GAMRequest *)adRequest + completionHandler: + (void (^)(id ad, NSError *error))completionHandler { + @throw [NSException exceptionWithName:@"MethodNotImplemented" + reason:@"Method `loadAd` must be overridden" + userInfo:nil]; +} + +- (void)sendAdEvent:(NSString *)type + requestId:(int)requestId + adUnitId:(NSString *)adUnitId + error:(NSDictionary *)error + data:(NSDictionary *)data { + [RNGoogleMobileAdsCommon sendAdEvent:[self getAdEventName] + requestId:@(requestId) + type:type + adUnitId:adUnitId + error:error + data:data]; +} + +- (void)loadWithRequestId:(int)requestId + adUnitId:(NSString *)adUnitId + adRequestOptions:(NSDictionary *)adRequestOptions { + GAMRequest *adRequest = [RNGoogleMobileAdsCommon buildAdRequest:adRequestOptions]; + RNGoogleMobileAdsFullScreenContentDelegate *delegate = + [[RNGoogleMobileAdsFullScreenContentDelegate alloc] initWithAdEventName:[self getAdEventName] + requestId:requestId + adUnitId:adUnitId]; + + __weak __typeof(self) weakSelf = self; + [self loadAd:adUnitId + adRequest:adRequest + completionHandler:^(id ad, NSError *error) { + if (error) { + NSDictionary *codeAndMessage = + [RNGoogleMobileAdsCommon getCodeAndMessageFromAdError:error]; + [weakSelf sendAdEvent:GOOGLE_MOBILE_ADS_EVENT_ERROR + requestId:requestId + adUnitId:adUnitId + error:codeAndMessage + data:nil]; + return; + } + + NSString *eventType = GOOGLE_MOBILE_ADS_EVENT_LOADED; + NSDictionary *data = nil; + + // Set up paid event handler + GADPaidEventHandler paidEventHandler = ^(GADAdValue *value) { + [weakSelf sendAdEvent:@"paid" + requestId:requestId + adUnitId:adUnitId + error:nil + data:@{ + @"value" : value.value, + @"precision" : @(value.precision), + @"currency" : value.currencyCode + }]; + }; + + if ([ad isKindOfClass:[GADRewardedAd class]]) { + [(GADRewardedAd *)ad setPaidEventHandler:paidEventHandler]; + } else if ([ad isKindOfClass:[GADRewardedInterstitialAd class]]) { + [(GADRewardedInterstitialAd *)ad setPaidEventHandler:paidEventHandler]; + } else if ([ad isKindOfClass:[GADInterstitialAd class]]) { + [(GADInterstitialAd *)ad setPaidEventHandler:paidEventHandler]; + } else if ([ad isKindOfClass:[GADAppOpenAd class]]) { + [(GADAppOpenAd *)ad setPaidEventHandler:paidEventHandler]; + } + + if ([ad isKindOfClass:[GADRewardedAd class]] || + [ad isKindOfClass:[GADRewardedInterstitialAd class]]) { + NSDictionary *serverSideVerificationOptions = + adRequestOptions[@"serverSideVerificationOptions"]; + if (serverSideVerificationOptions) { + GADServerSideVerificationOptions *options = + [[GADServerSideVerificationOptions alloc] init]; + options.userIdentifier = serverSideVerificationOptions[@"userId"]; + options.customRewardString = serverSideVerificationOptions[@"customData"]; + + if ([ad isKindOfClass:[GADRewardedAd class]]) { + [(GADRewardedAd *)ad setServerSideVerificationOptions:options]; + } else if ([ad isKindOfClass:[GADRewardedInterstitialAd class]]) { + [(GADRewardedInterstitialAd *)ad setServerSideVerificationOptions:options]; + } + } + + eventType = GOOGLE_MOBILE_ADS_EVENT_REWARDED_LOADED; + GADAdReward *adReward = + [(GADRewardedAd *)ad adReward] ?: [(GADRewardedInterstitialAd *)ad adReward]; + data = @{@"type" : adReward.type, @"amount" : adReward.amount}; + } + + if ([ad isKindOfClass:[GAMInterstitialAd class]]) { + [(GAMInterstitialAd *)ad setAppEventDelegate:delegate]; + } + + ad.fullScreenContentDelegate = delegate; + weakSelf.adMap[@(requestId)] = ad; + weakSelf.delegateMap[@(requestId)] = delegate; + + [weakSelf sendAdEvent:eventType requestId:requestId adUnitId:adUnitId error:nil data:data]; + }]; +} + +- (void)showWithRequestId:(int)requestId + adUnitId:(NSString *)adUnitId + showOptions:(NSDictionary *)showOptions + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject { + UIViewController *viewController = [RNGoogleMobileAdsCommon currentViewController]; + if (!viewController) { + [RNSharedUtils + rejectPromiseWithUserInfo:reject + userInfo:@{ + @"code" : @"nil-vc", + @"message" : + @"Ad attempted to show but the current View Controller was nil." + }]; + return; + } + + id ad = self.adMap[@(requestId)]; + if (!ad) { + [RNSharedUtils rejectPromiseWithUserInfo:reject + userInfo:@{ + @"code" : @"not-ready", + @"message" : @"Ad attempted to show but was not ready." + }]; + return; + } + + if ([ad isKindOfClass:[GADAppOpenAd class]]) { + [(GADAppOpenAd *)ad presentFromRootViewController:viewController]; + } else if ([ad isKindOfClass:[GADInterstitialAd class]]) { + [(GADInterstitialAd *)ad presentFromRootViewController:viewController]; + } else if ([ad isKindOfClass:[GADRewardedAd class]]) { + [(GADRewardedAd *)ad presentFromRootViewController:viewController + userDidEarnRewardHandler:^{ + NSDictionary *rewardData = @{ + @"type" : [(GADRewardedAd *)ad adReward].type, + @"amount" : [(GADRewardedAd *)ad adReward].amount + }; + [self sendAdEvent:GOOGLE_MOBILE_ADS_EVENT_REWARDED_EARNED_REWARD + requestId:requestId + adUnitId:adUnitId + error:nil + data:rewardData]; + }]; + } else if ([ad isKindOfClass:[GADRewardedInterstitialAd class]]) { + [(GADRewardedInterstitialAd *)ad + presentFromRootViewController:viewController + userDidEarnRewardHandler:^{ + NSDictionary *rewardData = @{ + @"type" : [(GADRewardedInterstitialAd *)ad adReward].type, + @"amount" : [(GADRewardedInterstitialAd *)ad adReward].amount + }; + [self sendAdEvent:GOOGLE_MOBILE_ADS_EVENT_REWARDED_EARNED_REWARD + requestId:requestId + adUnitId:adUnitId + error:nil + data:rewardData]; + }]; + } + + resolve(nil); +} + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.swift b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.swift deleted file mode 100644 index 9b33a4cb..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenAd.swift +++ /dev/null @@ -1,231 +0,0 @@ -/** - * 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. - * - */ - -#if !targetEnvironment(macCatalyst) - -import Foundation -import GoogleMobileAds - -class RNGoogleMobileAdsFullScreenAd: NSObject where T : GADFullScreenPresentingAd { - var adMap = Dictionary() - var delegateMap = Dictionary() - - deinit { - invalidate() - } - - func invalidate() { - adMap.removeAll() - delegateMap.removeAll() - } - - func getAdEventName() -> String { - fatalError("Method `getAdEventName` must be overriden") - } - - func loadAd( - adUnitId: String, - adRequest: GAMRequest, - completionHandler: @escaping (_ ad: T?, _ error: Error?) -> () - ) { - fatalError("Method `loadAd` must be overriden") - } - - func sendAdEvent( - _ type: String, - requestId: Int, - adUnitId: String, - error: Dictionary?, - data: Dictionary? - ) { - RNGoogleMobileAdsCommon.sendAdEvent( - getAdEventName(), - requestId: requestId as NSNumber, - type: type, - adUnitId: adUnitId, - error: error, - data: data - ) - } - - //MARK: - Load function - - func load( - requestId: Int, - adUnitId: String, - adRequestOptions: Dictionary - ) { - let adRequest = RNGoogleMobileAdsCommon.buildAdRequest(adRequestOptions)! - - let delegate = RNGoogleMobileAdsFullScreenContentDelegate( - adEventName: getAdEventName(), - requestId: requestId, - adUnitId: adUnitId - ) - - let completionHandler = { (ad: T?, error: Error?) -> () in - var eventType = GOOGLE_MOBILE_ADS_EVENT_LOADED - var data: Dictionary? = nil - if let error = error { - let codeAndMessage = RNGoogleMobileAdsCommon.getCodeAndMessage(fromAdError: error) - self.sendAdEvent( - GOOGLE_MOBILE_ADS_EVENT_ERROR, - requestId: requestId, - adUnitId: adUnitId, - error: codeAndMessage as? Dictionary, - data: nil - ) - return - } - - let paidEventHandler = {(value: GADAdValue) in - self.sendAdEvent( - "paid", - requestId: requestId, - adUnitId: adUnitId, - error: nil, - data: [ - "value": value.value, - "precision": value.precision.rawValue, - "currency": value.currencyCode, - ] - ); - }; - - (ad as? GADRewardedAd)?.paidEventHandler = paidEventHandler; - (ad as? GADRewardedInterstitialAd)?.paidEventHandler = paidEventHandler; - (ad as? GADInterstitialAd)?.paidEventHandler = paidEventHandler; - (ad as? GADAppOpenAd)?.paidEventHandler = paidEventHandler; - - if (ad is GADRewardedAd || ad is GADRewardedInterstitialAd) { - if let serverSideVerificationOptions = - adRequestOptions["serverSideVerificationOptions"] as? Dictionary { - let options = GADServerSideVerificationOptions() - - if let userId = serverSideVerificationOptions["userId"] as? String { - options.userIdentifier = userId - } - if let customData = serverSideVerificationOptions["customData"] as? String { - options.customRewardString = customData - } - - if let ad = ad as? GADRewardedAd { - ad.serverSideVerificationOptions = options - } - else if let ad = ad as? GADRewardedInterstitialAd { - ad.serverSideVerificationOptions = options - } - } - - eventType = GOOGLE_MOBILE_ADS_EVENT_REWARDED_LOADED - - let adReward = (ad as? GADRewardedAd)?.adReward ?? (ad as? GADRewardedInterstitialAd)?.adReward - data = [ - "type": adReward!.type, - "amount": adReward!.amount - ] - } - - if let ad = ad as? GAMInterstitialAd { - ad.appEventDelegate = delegate - } - - ad!.fullScreenContentDelegate = delegate - - self.adMap.updateValue(ad!, forKey: requestId) - self.delegateMap.updateValue(delegate, forKey: requestId) - self.sendAdEvent( - eventType, - requestId: requestId, - adUnitId: adUnitId, - error: nil, - data: data - ) - } - - loadAd(adUnitId: adUnitId, adRequest: adRequest, completionHandler: completionHandler) - } - - //MARK: - Show function - - func show( - requestId: Int, - adUnitId: String, - showOptions: Dictionary, - resolve: RCTPromiseResolveBlock?, - reject: RCTPromiseRejectBlock? - ) { - guard let viewController = RNGoogleMobileAdsCommon.currentViewController() else { - RNSharedUtils.rejectPromise(userInfo: reject, userInfo: [ - "code" : "nil-vc", - "message" : "Ad attempted to show but the current View Controller was nil.", - ]) - return - } - - guard let ad = adMap[requestId] else { - RNSharedUtils.rejectPromise(userInfo: reject, userInfo: [ - "code" : "not-ready", - "message" : "Ad attempted to show but was not ready.", - ]) - return - } - - var rewardData: Dictionary? = nil - if let adReward = - (ad as? GADRewardedAd)?.adReward ?? - (ad as? GADRewardedInterstitialAd)?.adReward { - rewardData = [ - "type": adReward.type, - "amount": adReward.amount - ] - } - let userDidEarnRewardHandler = { () -> Void in - self.sendAdEvent( - GOOGLE_MOBILE_ADS_EVENT_REWARDED_EARNED_REWARD, - requestId: requestId, - adUnitId: adUnitId, - error: nil, - data: rewardData - ) - } - - // TODO: Find way to compact this area - if let ad = ad as? GADAppOpenAd { - ad.present(fromRootViewController: viewController) - } - else if let ad = ad as? GADInterstitialAd { - ad.present(fromRootViewController: viewController) - } - else if let ad = ad as? GADRewardedAd { - ad.present( - fromRootViewController: viewController, - userDidEarnRewardHandler: userDidEarnRewardHandler - ) - } - else if let ad = ad as? GADRewardedInterstitialAd { - ad.present( - fromRootViewController: viewController, - userDidEarnRewardHandler: userDidEarnRewardHandler - ) - } - - resolve!(nil) - } -} - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.h b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.h new file mode 100644 index 00000000..0862ffe9 --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.h @@ -0,0 +1,36 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import +#import + +@interface RNGoogleMobileAdsFullScreenContentDelegate + : NSObject + +@property(nonatomic, strong, readonly) NSString *adEventName; +@property(nonatomic, assign, readonly) int requestId; +@property(nonatomic, strong, readonly) NSString *adUnitId; + +- (instancetype)initWithAdEventName:(NSString *)adEventName + requestId:(int)requestId + adUnitId:(NSString *)adUnitId; + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.mm b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.mm new file mode 100644 index 00000000..df697b32 --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.mm @@ -0,0 +1,80 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import "RNGoogleMobileAdsFullScreenContentDelegate.h" +#import "RNGoogleMobileAdsCommon.h" + +@implementation RNGoogleMobileAdsFullScreenContentDelegate + +- (instancetype)initWithAdEventName:(NSString *)adEventName + requestId:(int)requestId + adUnitId:(NSString *)adUnitId { + if (self = [super init]) { + _adEventName = adEventName; + _requestId = requestId; + _adUnitId = adUnitId; + } + return self; +} + +- (void)adWillPresentFullScreenContent:(id)ad { + [self sendAdEventWithType:GOOGLE_MOBILE_ADS_EVENT_OPENED error:nil data:nil]; +} + +- (void)ad:(id)ad + didFailToPresentFullScreenContentWithError:(NSError *)error { + NSDictionary *errorInfo = [RNGoogleMobileAdsCommon getCodeAndMessageFromAdError:error]; + [self sendAdEventWithType:GOOGLE_MOBILE_ADS_EVENT_ERROR error:errorInfo data:nil]; +} + +- (void)adDidDismissFullScreenContent:(id)ad { + [self sendAdEventWithType:GOOGLE_MOBILE_ADS_EVENT_CLOSED error:nil data:nil]; +} + +- (void)adDidRecordClick:(id)ad { + [self sendAdEventWithType:GOOGLE_MOBILE_ADS_EVENT_CLICKED error:nil data:nil]; +} + +- (void)adDidRecordImpression:(id)ad { + // Not implemented yet +} + +- (void)interstitialAd:(GADInterstitialAd *)interstitialAd + didReceiveAppEvent:(NSString *)name + withInfo:(nullable NSString *)info { + NSDictionary *data = @{@"name" : name, @"data" : info ?: @""}; + [self sendAdEventWithType:GOOGLE_MOBILE_ADS_EVENT_APP_EVENT error:nil data:data]; +} + +#pragma mark - Private + +- (void)sendAdEventWithType:(NSString *)type + error:(nullable NSDictionary *)error + data:(nullable NSDictionary *)data { + [RNGoogleMobileAdsCommon sendAdEvent:self.adEventName + requestId:@(self.requestId) + type:type + adUnitId:self.adUnitId + error:error + data:data]; +} + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.swift b/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.swift deleted file mode 100644 index e5f9ac3a..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.swift +++ /dev/null @@ -1,76 +0,0 @@ -#if !targetEnvironment(macCatalyst) - -import Foundation -import GoogleMobileAds - -class RNGoogleMobileAdsFullScreenContentDelegate: NSObject, GADFullScreenContentDelegate, GADAppEventDelegate { - let adEventName: String - let requestId: Int - let adUnitId: String - - init(adEventName: String, requestId: Int, adUnitId: String) { - self.adEventName = adEventName - self.requestId = requestId - self.adUnitId = adUnitId - } - - func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) { - sendAdEvent( - type: GOOGLE_MOBILE_ADS_EVENT_OPENED, - error: nil, - data: nil - ) - } - - func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) { - sendAdEvent( - type: GOOGLE_MOBILE_ADS_EVENT_ERROR, - error: RNGoogleMobileAdsCommon.getCodeAndMessage(fromAdError: error) as? Dictionary, - data: nil - ) - } - - func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) { - sendAdEvent( - type: GOOGLE_MOBILE_ADS_EVENT_CLOSED, - error: nil, - data: nil - ) - } - - func adDidRecordClick(_ ad: GADFullScreenPresentingAd) { - sendAdEvent( - type: GOOGLE_MOBILE_ADS_EVENT_CLICKED, - error: nil, - data: nil - ) - } - - func adDidRecordImpression(_ ad: GADFullScreenPresentingAd) { - // Not implemented yet - } - - func interstitialAd(_ interstitialAd: GADInterstitialAd, didReceiveAppEvent name: String, withInfo info: String?) { - sendAdEvent( - type: GOOGLE_MOBILE_ADS_EVENT_APP_EVENT, - error: nil, - data: [ - "name": name, - "data": info ?? "" - ] - ) - } - - private func sendAdEvent(type: String, error: Dictionary?, data: Dictionary?) { - RNGoogleMobileAdsCommon.sendAdEvent( - adEventName, - requestId: requestId as NSNumber, - type: type, - adUnitId: adUnitId, - error: error, - data: data - ) - } -} - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.h b/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.h new file mode 100644 index 00000000..24724b11 --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.h @@ -0,0 +1,36 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import + +#ifdef RCT_NEW_ARCH_ENABLED + +#import +@interface RNGoogleMobileAdsInterstitialModule : NSObject + +#else + +#import +@interface RNGoogleMobileAdsInterstitialModule : NSObject + +#endif + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.m b/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.m deleted file mode 100644 index 0382d160..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.m +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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. - * - */ - -#if !TARGET_OS_MACCATALYST - -#import - -@interface RCT_EXTERN_MODULE (RNGoogleMobileAdsInterstitialModule, NSObject) - -- (dispatch_queue_t)methodQueue { - return dispatch_get_main_queue(); -} - -+ (BOOL)requiresMainQueueSetup { - return YES; -} - -RCT_EXTERN_METHOD(interstitialLoad - : (nonnull NSNumber *)requestId forAdUnitId - : (nonnull NSString *)adUnitId withAdRequestOptions - : (nonnull NSDictionary *)adRequestOptions) - -RCT_EXTERN_METHOD(interstitialShow - : (nonnull NSNumber *)requestId forAdUnitId - : (nonnull NSString *)adUnitId withShowOptions - : (NSDictionary *)showOptions withResolve - : (RCTPromiseResolveBlock)resolve withReject - : (RCTPromiseRejectBlock)reject) - -@end - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.mm b/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.mm new file mode 100644 index 00000000..75957dfc --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.mm @@ -0,0 +1,102 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import "RNGoogleMobileAdsInterstitialModule.h" +#import +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNGoogleMobileAdsSpec.h" +#endif +#import "RNGoogleMobileAdsCommon.h" +#import "RNGoogleMobileAdsFullScreenAd.h" + +@interface RNGoogleMobileAdsInterstitialAd : RNGoogleMobileAdsFullScreenAd + +@end + +@implementation RNGoogleMobileAdsInterstitialAd + +- (NSString *)getAdEventName { + return GOOGLE_MOBILE_ADS_EVENT_INTERSTITIAL; +} + +- (void)loadAd:(NSString *)adUnitId + adRequest:(GAMRequest *)adRequest + completionHandler: + (void (^)(GAMInterstitialAd *_Nullable ad, NSError *_Nullable error))completionHandler { + [GAMInterstitialAd loadWithAdManagerAdUnitID:adUnitId + request:adRequest + completionHandler:completionHandler]; +} + +@end + +@implementation RNGoogleMobileAdsInterstitialModule { + RNGoogleMobileAdsInterstitialAd *_ad; +} + +RCT_EXPORT_MODULE(); + +- (dispatch_queue_t)methodQueue { + return dispatch_get_main_queue(); +} + +RCT_EXPORT_METHOD(interstitialLoad + : (double)requestId adUnitId + : (NSString *)adUnitId requestOptions + : (NSDictionary *)requestOptions) { + [_ad loadWithRequestId:requestId adUnitId:adUnitId adRequestOptions:requestOptions]; +} + +RCT_EXPORT_METHOD(interstitialShow + : (double)requestId adUnitId + : (NSString *)adUnitId showOptions + : (NSDictionary *)showOptions resolve + : (RCTPromiseResolveBlock)resolve reject + : (RCTPromiseRejectBlock)reject) { + [_ad showWithRequestId:requestId + adUnitId:adUnitId + showOptions:showOptions + resolve:resolve + reject:reject]; +} + +RCT_EXPORT_METHOD(invalidate) { [_ad invalidate]; } + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params { + return std::make_shared(params); +} +#endif + +- (instancetype)init { + self = [super init]; + if (self) { + _ad = [[RNGoogleMobileAdsInterstitialAd alloc] init]; + } + return self; +} + +- (void)dealloc { + [self invalidate]; +} + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.swift b/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.swift deleted file mode 100644 index f6d1f156..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.swift +++ /dev/null @@ -1,123 +0,0 @@ -/** - * 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. - * - */ - -#if !targetEnvironment(macCatalyst) - -import Foundation -import GoogleMobileAds - -@objc(RNGoogleMobileAdsInterstitialModule) -class RNGoogleMobileAdsInterstitialModule: NSObject { - let ad = RNGoogleMobileAdsInterstitialAd() - let gamAd = RNGoogleMobileAdsGAMInterstitialAd() - - deinit { - invalidate() - } - - @objc - func invalidate() { - ad.invalidate() - gamAd.invalidate() - } - - @objc(interstitialLoad:forAdUnitId:withAdRequestOptions:) - func interstitialLoad( - requestId: NSNumber, - adUnitId: String, - adRequestOptions: Dictionary - ) { - if (RNGoogleMobileAdsCommon.isAdManagerUnit(adUnitId)) { - gamAd.load( - requestId: requestId.intValue, - adUnitId: adUnitId, - adRequestOptions: adRequestOptions - ) - } else { - ad.load( - requestId: requestId.intValue, - adUnitId: adUnitId, - adRequestOptions: adRequestOptions - ) - } - } - - @objc(interstitialShow:forAdUnitId:withShowOptions:withResolve:withReject:) - func interstitialShow( - requestId: NSNumber, - adUnitId: String, - showOptions: Dictionary, - resolve: RCTPromiseResolveBlock?, - reject: RCTPromiseRejectBlock? - ) { - if (RNGoogleMobileAdsCommon.isAdManagerUnit(adUnitId)) { - gamAd.show( - requestId: requestId.intValue, - adUnitId: adUnitId, - showOptions: showOptions, - resolve: resolve, - reject: reject - ) - } else { - ad.show( - requestId: requestId.intValue, - adUnitId: adUnitId, - showOptions: showOptions, - resolve: resolve, - reject: reject - ) - } - } - - class RNGoogleMobileAdsInterstitialAd: RNGoogleMobileAdsFullScreenAd { - override func getAdEventName() -> String { - return GOOGLE_MOBILE_ADS_EVENT_INTERSTITIAL - } - - override func loadAd( - adUnitId: String, - adRequest: GAMRequest, - completionHandler: @escaping (GADInterstitialAd?, Error?) -> () - ) { - GADInterstitialAd.load( - withAdUnitID: adUnitId, - request: adRequest, - completionHandler: completionHandler - ) - } - } - - class RNGoogleMobileAdsGAMInterstitialAd: RNGoogleMobileAdsFullScreenAd { - override func getAdEventName() -> String { - return GOOGLE_MOBILE_ADS_EVENT_INTERSTITIAL - } - - override func loadAd( - adUnitId: String, - adRequest: GAMRequest, - completionHandler: @escaping (GAMInterstitialAd?, Error?) -> () - ) { - GAMInterstitialAd.load( - withAdManagerAdUnitID: adUnitId, - request: adRequest, - completionHandler: completionHandler - ) - } - } -} - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.h b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.h new file mode 100644 index 00000000..33d4f2c3 --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.h @@ -0,0 +1,37 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import + +#ifdef RCT_NEW_ARCH_ENABLED + +#import +@interface RNGoogleMobileAdsRewardedInterstitialModule + : NSObject + +#else + +#import +@interface RNGoogleMobileAdsRewardedInterstitialModule : NSObject + +#endif + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.m b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.m deleted file mode 100644 index 42e93763..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.m +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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. - * - */ - -#if !TARGET_OS_MACCATALYST - -#import - -@interface RCT_EXTERN_MODULE (RNGoogleMobileAdsRewardedInterstitialModule, NSObject) - -- (dispatch_queue_t)methodQueue { - return dispatch_get_main_queue(); -} - -+ (BOOL)requiresMainQueueSetup { - return YES; -} - -RCT_EXTERN_METHOD(rewardedInterstitialLoad - : (nonnull NSNumber *)requestId forAdUnitId - : (nonnull NSString *)adUnitId withAdRequestOptions - : (nonnull NSDictionary *)adRequestOptions) - -RCT_EXTERN_METHOD(rewardedInterstitialShow - : (nonnull NSNumber *)requestId forAdUnitId - : (nonnull NSString *)adUnitId withShowOptions - : (NSDictionary *)showOptions withResolve - : (RCTPromiseResolveBlock)resolve withReject - : (RCTPromiseRejectBlock)reject) - -@end - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.mm b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.mm new file mode 100644 index 00000000..cc1b938b --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.mm @@ -0,0 +1,102 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import "RNGoogleMobileAdsRewardedInterstitialModule.h" +#import +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNGoogleMobileAdsSpec.h" +#endif +#import "RNGoogleMobileAdsCommon.h" +#import "RNGoogleMobileAdsFullScreenAd.h" + +@interface RNGoogleMobileAdsRewardedInterstitialAd : RNGoogleMobileAdsFullScreenAd + +@end + +@implementation RNGoogleMobileAdsRewardedInterstitialAd + +- (NSString *)getAdEventName { + return GOOGLE_MOBILE_ADS_EVENT_REWARDED_INTERSTITIAL; +} + +- (void)loadAd:(NSString *)adUnitId + adRequest:(GAMRequest *)adRequest + completionHandler:(void (^)(GADRewardedInterstitialAd *_Nullable ad, + NSError *_Nullable error))completionHandler { + [GADRewardedInterstitialAd loadWithAdUnitID:adUnitId + request:adRequest + completionHandler:completionHandler]; +} + +@end + +@implementation RNGoogleMobileAdsRewardedInterstitialModule { + RNGoogleMobileAdsRewardedInterstitialAd *_ad; +} + +RCT_EXPORT_MODULE(); + +- (dispatch_queue_t)methodQueue { + return dispatch_get_main_queue(); +} + +RCT_EXPORT_METHOD(rewardedInterstitialLoad + : (double)requestId adUnitId + : (NSString *)adUnitId requestOptions + : (NSDictionary *)requestOptions) { + [_ad loadWithRequestId:requestId adUnitId:adUnitId adRequestOptions:requestOptions]; +} + +RCT_EXPORT_METHOD(rewardedInterstitialShow + : (double)requestId adUnitId + : (NSString *)adUnitId showOptions + : (NSDictionary *)showOptions resolve + : (RCTPromiseResolveBlock)resolve reject + : (RCTPromiseRejectBlock)reject) { + [_ad showWithRequestId:requestId + adUnitId:adUnitId + showOptions:showOptions + resolve:resolve + reject:reject]; +} + +RCT_EXPORT_METHOD(invalidate) { [_ad invalidate]; } + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params { + return std::make_shared(params); +} +#endif + +- (instancetype)init { + self = [super init]; + if (self) { + _ad = [[RNGoogleMobileAdsRewardedInterstitialAd alloc] init]; + } + return self; +} + +- (void)dealloc { + [self invalidate]; +} + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.swift b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.swift deleted file mode 100644 index df9938e6..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.swift +++ /dev/null @@ -1,85 +0,0 @@ -/** - * 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. - * - */ - -#if !targetEnvironment(macCatalyst) - -import Foundation -import GoogleMobileAds - -@objc(RNGoogleMobileAdsRewardedInterstitialModule) -class RNGoogleMobileAdsRewardedInterstitialModule: NSObject { - let ad = RNGoogleMobileAdsRewardedInterstitialAd() - - deinit { - invalidate() - } - - @objc - func invalidate() { - ad.invalidate() - } - - @objc(rewardedInterstitialLoad:forAdUnitId:withAdRequestOptions:) - func rewardedInterstitialLoad( - requestId: NSNumber, - adUnitId: String, - adRequestOptions: Dictionary - ) { - ad.load( - requestId: requestId.intValue, - adUnitId: adUnitId, - adRequestOptions: adRequestOptions - ) - } - - @objc(rewardedInterstitialShow:forAdUnitId:withShowOptions:withResolve:withReject:) - func rewardedInterstitialShow( - requestId: NSNumber, - adUnitId: String, - showOptions: Dictionary, - resolve: RCTPromiseResolveBlock?, - reject: RCTPromiseRejectBlock? - ) { - ad.show( - requestId: requestId.intValue, - adUnitId: adUnitId, - showOptions: showOptions, - resolve: resolve, - reject: reject - ) - } - - class RNGoogleMobileAdsRewardedInterstitialAd: RNGoogleMobileAdsFullScreenAd { - override func getAdEventName() -> String { - return GOOGLE_MOBILE_ADS_EVENT_REWARDED_INTERSTITIAL - } - - override func loadAd( - adUnitId: String, - adRequest: GAMRequest, - completionHandler: @escaping (GADRewardedInterstitialAd?, Error?) -> () - ) { - GADRewardedInterstitialAd.load( - withAdUnitID: adUnitId, - request: adRequest, - completionHandler: completionHandler - ) - } - } -} - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.h b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.h new file mode 100644 index 00000000..a65f917d --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.h @@ -0,0 +1,36 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import + +#ifdef RCT_NEW_ARCH_ENABLED + +#import +@interface RNGoogleMobileAdsRewardedModule : NSObject + +#else + +#import +@interface RNGoogleMobileAdsRewardedModule : NSObject + +#endif + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.m b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.m deleted file mode 100644 index 7920e773..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.m +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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. - * - */ - -#if !TARGET_OS_MACCATALYST - -#import - -@interface RCT_EXTERN_MODULE (RNGoogleMobileAdsRewardedModule, NSObject) - -- (dispatch_queue_t)methodQueue { - return dispatch_get_main_queue(); -} - -+ (BOOL)requiresMainQueueSetup { - return YES; -} - -RCT_EXTERN_METHOD(rewardedLoad - : (nonnull NSNumber *)requestId forAdUnitId - : (nonnull NSString *)adUnitId withAdRequestOptions - : (nonnull NSDictionary *)adRequestOptions) - -RCT_EXTERN_METHOD(rewardedShow - : (nonnull NSNumber *)requestId forAdUnitId - : (nonnull NSString *)adUnitId withShowOptions - : (NSDictionary *)showOptions withResolve - : (RCTPromiseResolveBlock)resolve withReject - : (RCTPromiseRejectBlock)reject) - -@end - -#endif diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.mm b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.mm new file mode 100644 index 00000000..172d0262 --- /dev/null +++ b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.mm @@ -0,0 +1,100 @@ +/** + * 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. + * + */ + +#if !TARGET_OS_MACCATALYST + +#import "RNGoogleMobileAdsRewardedModule.h" +#import +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNGoogleMobileAdsSpec.h" +#endif +#import "RNGoogleMobileAdsCommon.h" +#import "RNGoogleMobileAdsFullScreenAd.h" + +@interface RNGoogleMobileAdsRewardedAd : RNGoogleMobileAdsFullScreenAd + +@end + +@implementation RNGoogleMobileAdsRewardedAd + +- (NSString *)getAdEventName { + return GOOGLE_MOBILE_ADS_EVENT_REWARDED; +} + +- (void)loadAd:(NSString *)adUnitId + adRequest:(GAMRequest *)adRequest + completionHandler: + (void (^)(GADRewardedAd *_Nullable ad, NSError *_Nullable error))completionHandler { + [GADRewardedAd loadWithAdUnitID:adUnitId request:adRequest completionHandler:completionHandler]; +} + +@end + +@implementation RNGoogleMobileAdsRewardedModule { + RNGoogleMobileAdsRewardedAd *_ad; +} + +RCT_EXPORT_MODULE(); + +- (dispatch_queue_t)methodQueue { + return dispatch_get_main_queue(); +} + +RCT_EXPORT_METHOD(rewardedLoad + : (double)requestId adUnitId + : (NSString *)adUnitId requestOptions + : (NSDictionary *)requestOptions) { + [_ad loadWithRequestId:requestId adUnitId:adUnitId adRequestOptions:requestOptions]; +} + +RCT_EXPORT_METHOD(rewardedShow + : (double)requestId adUnitId + : (NSString *)adUnitId showOptions + : (NSDictionary *)showOptions resolve + : (RCTPromiseResolveBlock)resolve reject + : (RCTPromiseRejectBlock)reject) { + [_ad showWithRequestId:requestId + adUnitId:adUnitId + showOptions:showOptions + resolve:resolve + reject:reject]; +} + +RCT_EXPORT_METHOD(invalidate) { [_ad invalidate]; } + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params { + return std::make_shared(params); +} +#endif + +- (instancetype)init { + self = [super init]; + if (self) { + _ad = [[RNGoogleMobileAdsRewardedAd alloc] init]; + } + return self; +} + +- (void)dealloc { + [self invalidate]; +} + +@end + +#endif \ No newline at end of file diff --git a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.swift b/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.swift deleted file mode 100644 index 4bb061c0..00000000 --- a/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.swift +++ /dev/null @@ -1,85 +0,0 @@ -/** - * 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. - * - */ - -#if !targetEnvironment(macCatalyst) - -import Foundation -import GoogleMobileAds - -@objc(RNGoogleMobileAdsRewardedModule) -class RNGoogleMobileAdsRewardedModule: NSObject { - let ad = RNGoogleMobileAdsRewardedAd() - - deinit { - invalidate() - } - - @objc - func invalidate() { - ad.invalidate() - } - - @objc(rewardedLoad:forAdUnitId:withAdRequestOptions:) - func rewardedLoad( - requestId: NSNumber, - adUnitId: String, - adRequestOptions: Dictionary - ) { - ad.load( - requestId: requestId.intValue, - adUnitId: adUnitId, - adRequestOptions: adRequestOptions - ) - } - - @objc(rewardedShow:forAdUnitId:withShowOptions:withResolve:withReject:) - func rewardedShow( - requestId: NSNumber, - adUnitId: String, - showOptions: Dictionary, - resolve: RCTPromiseResolveBlock?, - reject: RCTPromiseRejectBlock? - ) { - ad.show( - requestId: requestId.intValue, - adUnitId: adUnitId, - showOptions: showOptions, - resolve: resolve, - reject: reject - ) - } - - class RNGoogleMobileAdsRewardedAd: RNGoogleMobileAdsFullScreenAd { - override func getAdEventName() -> String { - return GOOGLE_MOBILE_ADS_EVENT_REWARDED - } - - override func loadAd( - adUnitId: String, - adRequest: GAMRequest, - completionHandler: @escaping (GADRewardedAd?, Error?) -> () - ) { - GADRewardedAd.load( - withAdUnitID: adUnitId, - request: adRequest, - completionHandler: completionHandler - ) - } - } -} - -#endif diff --git a/jest.setup.ts b/jest.setup.ts index 5a729588..b26be8ea 100644 --- a/jest.setup.ts +++ b/jest.setup.ts @@ -17,15 +17,18 @@ jest.doMock('react-native', () => { eventsAddListener: jest.fn(), eventsNotifyReady: jest.fn(), }, - RNGoogleMobileAdsInterstitialModule: { - interstitialLoad: jest.fn(), - }, RNGoogleMobileAdsRewardedModule: {}, RNGoogleMobileAdsConsentModule: {}, }, TurboModuleRegistry: { ...ReactNative.TurboModuleRegistry, - getEnforcing: () => { + getEnforcing: moduleName => { + if (moduleName === 'RNGoogleMobileAdsInterstitialModule') { + return { + interstitialLoad: jest.fn(), + }; + } + return { initialize: jest.fn(), setRequestConfiguration: jest.fn(), @@ -40,7 +43,7 @@ jest.doMock('react-native', () => { ReactNative, ); }); -jest.doMock('./src/ads/GoogleMobileAdsBannerViewNativeComponent', () => { +jest.doMock('./src/specs/components/GoogleMobileAdsBannerViewNativeComponent', () => { return { __esModule: true, Commands: {}, diff --git a/package.json b/package.json index f6cc88a8..c89d6250 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,7 @@ "codegenConfig": { "name": "RNGoogleMobileAdsSpec", "type": "all", - "jsSrcsDir": "./src", + "jsSrcsDir": "./src/specs", "android": { "javaPackageName": "io.invertase.googlemobileads" } diff --git a/src/MobileAds.ts b/src/MobileAds.ts index c8e3345c..c10a021a 100644 --- a/src/MobileAds.ts +++ b/src/MobileAds.ts @@ -1,4 +1,4 @@ -import RNGoogleMobileAdsModule from './NativeGoogleMobileAdsModule'; +import RNGoogleMobileAdsModule from './specs/modules/NativeGoogleMobileAdsModule'; import { validateAdRequestConfiguration } from './validateAdRequestConfiguration'; import { SharedEventEmitter } from './internal/SharedEventEmitter'; import { GoogleMobileAdsNativeEventEmitter } from './internal/GoogleMobileAdsNativeEventEmitter'; diff --git a/src/NativeGoogleMobileAdsModule.ts b/src/NativeGoogleMobileAdsModule.ts deleted file mode 100644 index 68ca677b..00000000 --- a/src/NativeGoogleMobileAdsModule.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { TurboModule } from 'react-native'; -import { TurboModuleRegistry } from 'react-native'; -import { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; - -import { AdapterStatus } from './types'; - -export interface Spec extends TurboModule { - initialize(): Promise; - setRequestConfiguration(requestConfiguration?: UnsafeObject): Promise; - openAdInspector(): Promise; - openDebugMenu(adUnit: string): void; - setAppVolume(volume: number): void; - setAppMuted(muted: boolean): void; -} - -export default TurboModuleRegistry.getEnforcing('RNGoogleMobileAdsModule'); diff --git a/src/ads/AppOpenAd.ts b/src/ads/AppOpenAd.ts index 23ff972c..8464039d 100644 --- a/src/ads/AppOpenAd.ts +++ b/src/ads/AppOpenAd.ts @@ -22,6 +22,7 @@ import { AdEventType } from '../AdEventType'; import { AdEventListener } from '../types/AdEventListener'; import { AdEventsListener } from '../types/AdEventsListener'; import { RequestOptions } from '../types/RequestOptions'; +import NativeAppOpenModule from '../specs/modules/NativeAppOpenModule'; export class AppOpenAd extends MobileAd { protected static _appOpenRequest = 0; @@ -43,9 +44,10 @@ export class AppOpenAd extends MobileAd { const requestId = AppOpenAd._appOpenRequest++; return new AppOpenAd( 'app_open', - 'RNGoogleMobileAdsAppOpenModule', requestId, adUnitId, + NativeAppOpenModule.appOpenLoad, + NativeAppOpenModule.appOpenShow, options, ); } diff --git a/src/ads/BannerAd.tsx b/src/ads/BannerAd.tsx index 3e515ecf..f45b6f10 100644 --- a/src/ads/BannerAd.tsx +++ b/src/ads/BannerAd.tsx @@ -18,7 +18,9 @@ import React, { createRef } from 'react'; import { BannerAdProps } from '../types/BannerAdProps'; import { BaseAd } from './BaseAd'; -import GoogleMobileAdsBannerView, { Commands } from './GoogleMobileAdsBannerViewNativeComponent'; +import GoogleMobileAdsBannerView, { + Commands, +} from '../specs/components/GoogleMobileAdsBannerViewNativeComponent'; export class BannerAd extends React.Component { private ref = createRef>(); diff --git a/src/ads/BaseAd.tsx b/src/ads/BaseAd.tsx index 1a32ba0b..9c0a2947 100644 --- a/src/ads/BaseAd.tsx +++ b/src/ads/BaseAd.tsx @@ -21,8 +21,8 @@ import { DimensionValue, NativeSyntheticEvent, Platform } from 'react-native'; import { isFunction } from '../common'; import { RevenuePrecisions } from '../common/constants'; import { NativeError } from '../internal/NativeError'; -import GoogleMobileAdsBannerView from './GoogleMobileAdsBannerViewNativeComponent'; -import type { NativeEvent } from './GoogleMobileAdsBannerViewNativeComponent'; +import GoogleMobileAdsBannerView from '../specs/components/GoogleMobileAdsBannerViewNativeComponent'; +import type { NativeEvent } from '../specs/components/GoogleMobileAdsBannerViewNativeComponent'; import { BannerAdSize, GAMBannerAdSize } from '../BannerAdSize'; import { validateAdRequestOptions } from '../validateAdRequestOptions'; import { GAMBannerAdProps } from '../types/BannerAdProps'; diff --git a/src/ads/GAMBannerAd.tsx b/src/ads/GAMBannerAd.tsx index e8f7df1d..aacae54a 100644 --- a/src/ads/GAMBannerAd.tsx +++ b/src/ads/GAMBannerAd.tsx @@ -18,7 +18,9 @@ import React, { createRef } from 'react'; import { GAMBannerAdProps } from '../types/BannerAdProps'; import { BaseAd } from './BaseAd'; -import GoogleMobileAdsBannerView, { Commands } from './GoogleMobileAdsBannerViewNativeComponent'; +import GoogleMobileAdsBannerView, { + Commands, +} from '../specs/components/GoogleMobileAdsBannerViewNativeComponent'; export class GAMBannerAd extends React.Component { private ref = createRef>(); diff --git a/src/ads/InterstitialAd.ts b/src/ads/InterstitialAd.ts index 08cd6a81..2af6eb40 100644 --- a/src/ads/InterstitialAd.ts +++ b/src/ads/InterstitialAd.ts @@ -22,6 +22,7 @@ import { AdEventType } from '../AdEventType'; import { AdEventListener } from '../types/AdEventListener'; import { AdEventsListener } from '../types/AdEventsListener'; import { RequestOptions } from '../types/RequestOptions'; +import NativeInterstitialModule from '../specs/modules/NativeInterstitialModule'; /** * A class for interacting and showing Interstitial Ads. @@ -103,9 +104,10 @@ export class InterstitialAd extends MobileAd { const requestId = InterstitialAd._interstitialRequest++; return new InterstitialAd( 'interstitial', - 'RNGoogleMobileAdsInterstitialModule', requestId, adUnitId, + NativeInterstitialModule.interstitialLoad, + NativeInterstitialModule.interstitialShow, options, ); } diff --git a/src/ads/MobileAd.ts b/src/ads/MobileAd.ts index 56d6b9fd..7dbb9758 100644 --- a/src/ads/MobileAd.ts +++ b/src/ads/MobileAd.ts @@ -15,7 +15,7 @@ * */ -import { EmitterSubscription, NativeModules } from 'react-native'; +import { EmitterSubscription } from 'react-native'; import { isFunction, isOneOf } from '../common'; import { NativeError } from '../internal/NativeError'; import { AdEventType } from '../AdEventType'; @@ -32,11 +32,6 @@ import { AppEvent } from '../types/AppEvent'; import { validateAdShowOptions } from '../validateAdShowOptions'; type AdType = 'app_open' | 'interstitial' | 'rewarded' | 'rewarded_interstitial'; -type NativeModule = - | 'RNGoogleMobileAdsAppOpenModule' - | 'RNGoogleMobileAdsInterstitialModule' - | 'RNGoogleMobileAdsRewardedModule' - | 'RNGoogleMobileAdsRewardedInterstitialModule'; type EventType = AdEventType | RewardedAdEventType | GAMAdEventType; type AdLoadFunction = (requestId: number, adUnitId: string, requestOptions: RequestOptions) => void; type AdShowFunction = ( @@ -47,9 +42,10 @@ type AdShowFunction = ( export abstract class MobileAd implements MobileAdInterface { protected _type: AdType; - protected _nativeModule: NativeModule; protected _requestId: number; protected _adUnitId: string; + protected _adLoadFunction: AdLoadFunction; + protected _adShowFunction: AdShowFunction; protected _requestOptions: RequestOptions; protected _loaded: boolean; protected _isLoadCalled: boolean; @@ -61,15 +57,17 @@ export abstract class MobileAd implements MobileAdInterface { protected constructor( type: AdType, - nativeModule: NativeModule, requestId: number, adUnitId: string, + adLoadFunction: AdLoadFunction, + adShowFunction: AdShowFunction, requestOptions: RequestOptions, ) { this._type = type; - this._nativeModule = nativeModule; this._requestId = requestId; this._adUnitId = adUnitId; + this._adLoadFunction = adLoadFunction; + this._adShowFunction = adShowFunction; this._requestOptions = requestOptions; this._loaded = false; @@ -177,18 +175,6 @@ export abstract class MobileAd implements MobileAdInterface { return this.constructor.name; } - protected get _camelCaseType() { - let type: 'appOpen' | 'interstitial' | 'rewarded' | 'rewardedInterstitial'; - if (this._type === 'app_open') { - type = 'appOpen'; - } else if (this._type === 'rewarded_interstitial') { - type = 'rewardedInterstitial'; - } else { - type = this._type; - } - return type; - } - public load() { // Prevent multiple load calls if (this._loaded || this._isLoadCalled) { @@ -196,8 +182,7 @@ export abstract class MobileAd implements MobileAdInterface { } this._isLoadCalled = true; - const load: AdLoadFunction = NativeModules[this._nativeModule][`${this._camelCaseType}Load`]; - load(this._requestId, this._adUnitId, this._requestOptions); + this._adLoadFunction(this._requestId, this._adUnitId, this._requestOptions); } public show(showOptions?: AdShowOptions) { @@ -218,8 +203,7 @@ export abstract class MobileAd implements MobileAdInterface { } } - const show: AdShowFunction = NativeModules[this._nativeModule][`${this._camelCaseType}Show`]; - return show(this._requestId, this._adUnitId, options); + return this._adShowFunction(this._requestId, this._adUnitId, options); } public abstract addAdEventsListener(listener: AdEventsListener): () => void; diff --git a/src/ads/RewardedAd.ts b/src/ads/RewardedAd.ts index 75232692..8a52e303 100644 --- a/src/ads/RewardedAd.ts +++ b/src/ads/RewardedAd.ts @@ -23,6 +23,7 @@ import { RewardedAdEventType } from '../RewardedAdEventType'; import { AdEventListener } from '../types/AdEventListener'; import { AdEventsListener } from '../types/AdEventsListener'; import { RequestOptions } from '../types/RequestOptions'; +import NativeRewardedModule from '../specs/modules/NativeRewardedModule'; /** * A class for interacting and showing Rewarded Ads. @@ -113,9 +114,10 @@ export class RewardedAd extends MobileAd { const requestId = RewardedAd._rewardedRequest++; return new RewardedAd( 'rewarded', - 'RNGoogleMobileAdsRewardedModule', requestId, adUnitId, + NativeRewardedModule.rewardedLoad, + NativeRewardedModule.rewardedShow, options, ); } diff --git a/src/ads/RewardedInterstitialAd.ts b/src/ads/RewardedInterstitialAd.ts index 38a7bba5..21560025 100644 --- a/src/ads/RewardedInterstitialAd.ts +++ b/src/ads/RewardedInterstitialAd.ts @@ -23,6 +23,7 @@ import { RewardedAdEventType } from '../RewardedAdEventType'; import { AdEventListener } from '../types/AdEventListener'; import { AdEventsListener } from '../types/AdEventsListener'; import { RequestOptions } from '../types/RequestOptions'; +import NativeRewardedInterstitialModule from '../specs/modules/NativeRewardedInterstitialModule'; /** * A class for interacting and showing Rewarded Interstitial Ads. @@ -115,9 +116,10 @@ export class RewardedInterstitialAd extends MobileAd { const requestId = RewardedInterstitialAd._rewardedInterstitialRequest++; return new RewardedInterstitialAd( 'rewarded_interstitial', - 'RNGoogleMobileAdsRewardedInterstitialModule', requestId, adUnitId, + NativeRewardedInterstitialModule.rewardedInterstitialLoad, + NativeRewardedInterstitialModule.rewardedInterstitialShow, options, ); } diff --git a/src/ads/GoogleMobileAdsBannerViewNativeComponent.ts b/src/specs/components/GoogleMobileAdsBannerViewNativeComponent.ts similarity index 100% rename from src/ads/GoogleMobileAdsBannerViewNativeComponent.ts rename to src/specs/components/GoogleMobileAdsBannerViewNativeComponent.ts diff --git a/src/specs/modules/NativeAppOpenModule.ts b/src/specs/modules/NativeAppOpenModule.ts new file mode 100644 index 00000000..d391fb36 --- /dev/null +++ b/src/specs/modules/NativeAppOpenModule.ts @@ -0,0 +1,26 @@ +/** + * 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 { TurboModule, TurboModuleRegistry } from 'react-native'; +import { Double, UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; + +export interface Spec extends TurboModule { + appOpenLoad(requestId: Double, adUnitId: string, requestOptions: UnsafeObject): void; + appOpenShow(requestId: Double, adUnitId: string, showOptions?: UnsafeObject): Promise; +} + +export default TurboModuleRegistry.getEnforcing('RNGoogleMobileAdsAppOpenModule'); diff --git a/src/specs/modules/NativeGoogleMobileAdsModule.ts b/src/specs/modules/NativeGoogleMobileAdsModule.ts new file mode 100644 index 00000000..4225e654 --- /dev/null +++ b/src/specs/modules/NativeGoogleMobileAdsModule.ts @@ -0,0 +1,33 @@ +/** + * 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 type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; +import { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; + +import { AdapterStatus } from '../../types'; + +export interface Spec extends TurboModule { + initialize(): Promise; + setRequestConfiguration(requestConfiguration?: UnsafeObject): Promise; + openAdInspector(): Promise; + openDebugMenu(adUnit: string): void; + setAppVolume(volume: number): void; + setAppMuted(muted: boolean): void; +} + +export default TurboModuleRegistry.getEnforcing('RNGoogleMobileAdsModule'); diff --git a/src/specs/modules/NativeInterstitialModule.ts b/src/specs/modules/NativeInterstitialModule.ts new file mode 100644 index 00000000..bcf8f1b4 --- /dev/null +++ b/src/specs/modules/NativeInterstitialModule.ts @@ -0,0 +1,26 @@ +/** + * 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 { TurboModule, TurboModuleRegistry } from 'react-native'; +import { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; + +export interface Spec extends TurboModule { + interstitialLoad(requestId: number, adUnitId: string, requestOptions: UnsafeObject): void; + interstitialShow(requestId: number, adUnitId: string, showOptions?: UnsafeObject): Promise; +} + +export default TurboModuleRegistry.getEnforcing('RNGoogleMobileAdsInterstitialModule'); diff --git a/src/specs/modules/NativeRewardedInterstitialModule.ts b/src/specs/modules/NativeRewardedInterstitialModule.ts new file mode 100644 index 00000000..1c7c7a6b --- /dev/null +++ b/src/specs/modules/NativeRewardedInterstitialModule.ts @@ -0,0 +1,32 @@ +/** + * 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 { TurboModule, TurboModuleRegistry } from 'react-native'; +import { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; + +export interface Spec extends TurboModule { + rewardedInterstitialLoad(requestId: number, adUnitId: string, requestOptions: UnsafeObject): void; + rewardedInterstitialShow( + requestId: number, + adUnitId: string, + showOptions?: UnsafeObject, + ): Promise; +} + +export default TurboModuleRegistry.getEnforcing( + 'RNGoogleMobileAdsRewardedInterstitialModule', +); diff --git a/src/specs/modules/NativeRewardedModule.ts b/src/specs/modules/NativeRewardedModule.ts new file mode 100644 index 00000000..8f615c57 --- /dev/null +++ b/src/specs/modules/NativeRewardedModule.ts @@ -0,0 +1,26 @@ +/** + * 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 { TurboModule, TurboModuleRegistry } from 'react-native'; +import { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; + +export interface Spec extends TurboModule { + rewardedLoad(requestId: number, adUnitId: string, requestOptions: UnsafeObject): void; + rewardedShow(requestId: number, adUnitId: string, showOptions?: UnsafeObject): Promise; +} + +export default TurboModuleRegistry.getEnforcing('RNGoogleMobileAdsRewardedModule');