[ios][admob] Implement NativeExpress

This commit is contained in:
Elliot Hesp 2017-06-16 17:40:05 +01:00
parent 0e27d7345e
commit d159d9bb6b
9 changed files with 189 additions and 6 deletions

View File

@ -282,7 +282,7 @@ adverts (e.g. Interstitial) they're available via the `on` method.
##### onAdLoaded(config: `Object`)
!> The config is not provided for Interstitial or Rewarded Video adverts.
On successful response from the AdMob servers.
On successful response from the AdMob servers. This is also called when a new banner is automatically loaded from the AdMob servers if the current one expires.
Returns an object of config data related to the loaded advert:
```js

View File

@ -21,7 +21,7 @@
@end
#else
@interface RNFirebaseAdMobBanner : NSObject <RCTBridgeModule> {
@interface BannerComponent : NSObject <RCTBridgeModule> {
}
@end

View File

@ -0,0 +1,31 @@
#import <React/RCTComponent.h>
#import <React/RCTBridgeModule.h>
#if __has_include(<GoogleMobileAds/GADMobileAds.h>)
#import "GoogleMobileAds/GADNativeExpressAdView.h"
#import "GoogleMobileAds/GADVideoControllerDelegate.h"
@interface NativeExpressComponent : UIView <GADNativeExpressAdViewDelegate, GADVideoControllerDelegate>
@property GADNativeExpressAdView *banner;
//@property(nonatomic, weak) IBOutlet GADNativeExpressAdView *banner;
@property (nonatomic, assign) BOOL requested;
@property (nonatomic, copy) NSString *size;
@property (nonatomic, copy) NSString *unitId;
@property (nonatomic, copy) NSDictionary *request;
@property (nonatomic, copy) NSDictionary *video;
@property (nonatomic, copy) RCTBubblingEventBlock onBannerEvent;
- (void)requestAd;
@end
#else
@interface NativeExpressComponent : NSObject <RCTBridgeModule> {
}
@end
#endif

View File

@ -0,0 +1,96 @@
#import "NativeExpressComponent.h"
#import "RNFirebaseAdMob.h"
#import "React/UIView+React.h"
@implementation NativeExpressComponent
- (void)initBanner:(GADAdSize)adSize {
if (_requested) {
[_banner removeFromSuperview];
}
_banner = [[GADNativeExpressAdView alloc] initWithAdSize:adSize];
_banner.rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
_banner.delegate = self;
_banner.videoController.delegate = self;
}
- (void)setUnitId:(NSString *)unitId {
_unitId = unitId;
[self requestAd];
}
- (void)setSize:(NSString *)size {
_size = size;
[self requestAd];
}
- (void)setRequest:(NSDictionary *)request {
_request = request;
[self requestAd];
}
- (void)setVideo:(NSDictionary *)video {
_video = video;
[self requestAd];
}
- (void)requestAd {
if (_unitId == nil || _size == nil || _request == nil || _video == nil) {
[self setRequested:NO];
return;
}
[self initBanner:[RNFirebaseAdMob stringToAdSize:_size]];
[self addSubview:_banner];
[self sendEvent:@"onSizeChange" payload:@{
@"width": @(_banner.bounds.size.width),
@"height": @(_banner.bounds.size.height),
}];
_banner.adUnitID = _unitId;
[self setRequested:YES];
[_banner setAdOptions:@[[RNFirebaseAdMob buildVideoOptions:_video]]];
[_banner loadRequest:[RNFirebaseAdMob buildRequest:_request]];
}
- (void)sendEvent:(NSString *)type payload:(NSDictionary *_Nullable)payload {
self.onBannerEvent(@{
@"type": type,
@"payload": payload != nil ? payload : [NSNull null],
});
}
- (void)nativeExpressAdViewDidReceiveAd:(GADNativeExpressAdView *)adView {
[self sendEvent:@"onAdLoaded" payload:@{
@"width": @(adView.bounds.size.width),
@"height": @(adView.bounds.size.height),
@"hasVideoContent": @(adView.videoController.hasVideoContent),
}];
}
- (void)nativeExpressAdView:(nonnull GADNativeExpressAdView *)nativeExpressAdView didFailToReceiveAdWithError:(nonnull GADRequestError *)error {
[self sendEvent:@"onAdFailedToLoad" payload:[RNFirebaseAdMob errorCodeToDictionary:error]];
}
- (void)nativeExpressAdViewWillPresentScreen:(GADNativeExpressAdView *)adView {
[self sendEvent:@"onAdOpened" payload:nil];
}
- (void)nativeExpressAdViewWillDismissScreen:(GADNativeExpressAdView *)adView {
// not in use
}
- (void)nativeExpressAdViewDidDismissScreen:(GADNativeExpressAdView *)adView {
[self sendEvent:@"onAdClosed" payload:nil];
}
- (void)nativeExpressAdViewWillLeaveApplication:(GADNativeExpressAdView *)adView {
[self sendEvent:@"onAdLeftApplication" payload:nil];
}
- (void)videoControllerDidEndVideoPlayback:(GADVideoController *)videoController {
[self sendEvent:@"onVideoEnd" payload:nil];
}
@end

View File

@ -17,6 +17,7 @@
@property NSMutableDictionary *rewardedVideos;
+ (GADRequest *)buildRequest:(NSDictionary *)request;
+ (GADVideoOptions *)buildVideoOptions:(NSDictionary *)options;
+ (NSDictionary *)errorCodeToDictionary:(NSError *)error;
+ (GADAdSize)stringToAdSize:(NSString *)value;
@end

View File

@ -88,8 +88,8 @@ RCT_EXPORT_METHOD(rewardedVideoShowAd:
if (request[@"keywords"]) builder.keywords = request[@"keywords"];
if (request[@"testDevices"]) {
NSArray * devices = request[@"testDevices"];
NSMutableArray * testDevices = [[NSMutableArray alloc] init];
NSArray *devices = request[@"testDevices"];
NSMutableArray *testDevices = [[NSMutableArray alloc] init];
for (id device in devices) {
if ([device isEqual:@"DEVICE_ID_EMULATOR"]) {
@ -117,6 +117,12 @@ RCT_EXPORT_METHOD(rewardedVideoShowAd:
return builder;
}
+ (GADVideoOptions *)buildVideoOptions:(NSDictionary *)options {
GADVideoOptions *builder = [[GADVideoOptions alloc] init];
builder.startMuted = (BOOL) options[@"startMuted"];
return builder;
}
+ (NSDictionary *)errorCodeToDictionary:(NSError *)error {
NSString *code;
NSString *message;
@ -162,6 +168,22 @@ RCT_EXPORT_METHOD(rewardedVideoShowAd:
}
+ (GADAdSize)stringToAdSize:(NSString *)value {
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"([0-9]+)x([0-9]+)" options:0 error:&error];
NSArray *matches = [regex matchesInString:value options:0 range:NSMakeRange(0, [value length])];
for (NSTextCheckingResult *match in matches) {
NSString *matchText = [value substringWithRange:[match range]];
if (matchText) {
NSArray *values = [matchText componentsSeparatedByString:@"x"];
CGFloat width = (CGFloat)[values[0] intValue];
CGFloat height = (CGFloat)[values[1] intValue];
return GADAdSizeFromCGSize(CGSizeMake(width, height));
}
}
value = [value uppercaseString];
if ([value isEqualToString:@"BANNER"]) {
return kGADAdSizeBanner;
} else if ([value isEqualToString:@"LARGE_BANNER"]) {

View File

@ -0,0 +1,5 @@
#import <React/RCTViewManager.h>
@interface RNFirebaseAdMobNativeExpressManager : RCTViewManager
@end

View File

@ -0,0 +1,28 @@
#import "RNFirebaseAdMobNativeExpressManager.h"
#import "NativeExpressComponent.h"
@implementation RNFirebaseAdMobNativeExpressManager
RCT_EXPORT_MODULE();
@synthesize bridge = _bridge;
- (UIView *)view
{
return [[NativeExpressComponent alloc] init];
}
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXPORT_VIEW_PROPERTY(size, NSString);
RCT_EXPORT_VIEW_PROPERTY(unitId, NSString);
RCT_EXPORT_VIEW_PROPERTY(request, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(video, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(onBannerEvent, RCTBubblingEventBlock);
@end

View File

@ -1,5 +1,4 @@
import React from 'react';
import { requireNativeComponent } from 'react-native';
import AdMobComponent from './AdMobComponent';
function NativeExpress({ ...props }) {
@ -14,7 +13,8 @@ function NativeExpress({ ...props }) {
NativeExpress.propTypes = AdMobComponent.propTypes;
NativeExpress.defaultProps = {
unitId: 'ca-app-pub-3940256099942544/2177258514',
// unitId: 'ca-app-pub-3940256099942544/2177258514',
unitId: 'ca-app-pub-3940256099942544/8897359316',
size: 'SMART_BANNER',
};