blob: a49f457b08b6d0ef26d2ea206bc55ab588ad72d1 [file] [log] [blame]
// Copyright 2017, the Flutter project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#import "FirebaseAdMobPlugin.h"
#import <UIKit/UIKit.h>
#import "FLTMobileAd.h"
#import "FLTRewardedVideoAdWrapper.h"
#import "Firebase/Firebase.h"
@interface NSError (FlutterError)
@property(readonly, nonatomic) FlutterError *flutterError;
@end
@implementation NSError (FlutterError)
- (FlutterError *)flutterError {
return [FlutterError errorWithCode:[NSString stringWithFormat:@"%ld", (long)self.code]
message:self.domain
details:self.localizedDescription];
}
@end
@interface FLTFirebaseAdMobPlugin ()
@property(nonatomic, retain) FlutterMethodChannel *channel;
@property(nonatomic, strong) FLTRewardedVideoAdWrapper *rewardedWrapper;
@end
@implementation FLTFirebaseAdMobPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FLTFirebaseAdMobPlugin *instance = [[FLTFirebaseAdMobPlugin alloc] init];
instance.channel =
[FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_admob"
binaryMessenger:[registrar messenger]];
[registrar addMethodCallDelegate:instance channel:instance.channel];
instance.rewardedWrapper = [[FLTRewardedVideoAdWrapper alloc] initWithChannel:instance.channel];
}
- (instancetype)init {
self = [super init];
if (self && ![FIRApp defaultApp]) {
FLTLogWarning(@"[FIRApp configure]");
[FIRApp configure];
}
return self;
}
- (void)dealloc {
[self.channel setMethodCallHandler:nil];
self.channel = nil;
}
- (void)callInitialize:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *appId = (NSString *)call.arguments[@"appId"];
if (appId == nil || [appId length] == 0) {
result([FlutterError errorWithCode:@"no_app_id"
message:@"a non-empty AdMob appId was not provided"
details:nil]);
return;
}
[FLTMobileAd configureWithAppId:appId];
result([NSNumber numberWithBool:YES]);
}
- (void)callLoadBannerAdWithId:(NSNumber *)id
channel:(FlutterMethodChannel *)channel
call:(FlutterMethodCall *)call
result:(FlutterResult)result {
NSString *adUnitId = (NSString *)call.arguments[@"adUnitId"];
if (adUnitId == nil || [adUnitId length] == 0) {
NSString *message =
[NSString stringWithFormat:@"a null or empty adUnitId was provided for %@", id];
result([FlutterError errorWithCode:@"no_adunit_id" message:message details:nil]);
return;
}
NSNumber *widthArg = (NSNumber *)call.arguments[@"width"];
NSNumber *heightArg = (NSNumber *)call.arguments[@"height"];
if (widthArg == nil || heightArg == nil) {
NSString *message =
[NSString stringWithFormat:@"a null height or width was provided for banner id=%@", id];
result([FlutterError errorWithCode:@"invalid_adsize" message:message details:nil]);
return;
}
NSString *adSizeTypeArg = (NSString *)call.arguments[@"adSizeType"];
FLTLogWarning(@"Size Type: %@", adSizeTypeArg);
if (adSizeTypeArg == nil || (![adSizeTypeArg isEqualToString:@"AdSizeType.SmartBanner"] &&
![adSizeTypeArg isEqualToString:@"AdSizeType.WidthAndHeight"])) {
NSString *message = [NSString
stringWithFormat:@"a null or invalid ad size type was provided for banner id=%@", id];
result([FlutterError errorWithCode:@"invalid_adsizetype" message:message details:nil]);
return;
}
int width = [widthArg intValue];
int height = [heightArg intValue];
if ([adSizeTypeArg isEqualToString:@"AdSizeType.WidthAndHeight"] && (width <= 0 || height <= 0)) {
NSString *message =
[NSString stringWithFormat:@"an invalid AdSize (%d, %d) was provided for banner id=%@",
width, height, id];
result([FlutterError errorWithCode:@"invalid_adsize" message:message details:nil]);
return;
}
GADAdSize adSize;
if ([adSizeTypeArg isEqualToString:@"AdSizeType.SmartBanner"]) {
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
adSize = kGADAdSizeSmartBannerPortrait;
} else {
adSize = kGADAdSizeSmartBannerLandscape;
}
} else {
adSize = GADAdSizeFromCGSize(CGSizeMake(width, height));
}
FLTBannerAd *banner = [FLTBannerAd withId:id adSize:adSize channel:self.channel];
if (banner.status != CREATED) {
if (banner.status == FAILED) {
NSString *message = [NSString stringWithFormat:@"cannot reload a failed ad=%@", banner];
result([FlutterError errorWithCode:@"load_failed_ad" message:message details:nil]);
} else {
result([NSNumber numberWithBool:YES]); // The ad was already loaded.
}
}
NSDictionary *targetingInfo = (NSDictionary *)call.arguments[@"targetingInfo"];
[banner loadWithAdUnitId:adUnitId targetingInfo:targetingInfo];
result([NSNumber numberWithBool:YES]);
}
- (void)callLoadInterstitialAd:(FLTMobileAd *)ad
call:(FlutterMethodCall *)call
result:(FlutterResult)result {
if (ad.status != CREATED) {
if (ad.status == FAILED) {
NSString *message = [NSString stringWithFormat:@"cannot reload a failed ad=%@", ad];
result([FlutterError errorWithCode:@"load_failed_ad" message:message details:nil]);
} else {
result([NSNumber numberWithBool:YES]); // The ad was already loaded.
}
}
NSString *adUnitId = (NSString *)call.arguments[@"adUnitId"];
if (adUnitId == nil || [adUnitId length] == 0) {
NSString *message =
[NSString stringWithFormat:@"a null or emtpy adUnitId was provided for %@", ad];
result([FlutterError errorWithCode:@"no_adunit_id" message:message details:nil]);
return;
}
NSDictionary *targetingInfo = (NSDictionary *)call.arguments[@"targetingInfo"];
[ad loadWithAdUnitId:adUnitId targetingInfo:targetingInfo];
result([NSNumber numberWithBool:YES]);
}
- (void)callLoadRewardedVideoAd:(FlutterMethodCall *)call result:(FlutterResult)result {
if (self.rewardedWrapper.status == FLTRewardedVideoAdStatusLoading ||
self.rewardedWrapper.status == FLTRewardedVideoAdStatusLoaded) {
result([NSNumber numberWithBool:YES]); // The ad is loaded or about to be.
}
NSString *adUnitId = (NSString *)call.arguments[@"adUnitId"];
if (adUnitId == nil || [adUnitId length] == 0) {
result([FlutterError errorWithCode:@"no_ad_unit_id"
message:@"a non-empty adUnitId was not provided for rewarded video."
details:nil]);
return;
}
NSDictionary *targetingInfo = (NSDictionary *)call.arguments[@"targetingInfo"];
if (targetingInfo == nil) {
result([FlutterError
errorWithCode:@"no_targeting_info"
message:@"a null targetingInfo object was provided for rewarded video."
details:nil]);
return;
}
[self.rewardedWrapper loadWithAdUnitId:adUnitId targetingInfo:targetingInfo];
result([NSNumber numberWithBool:YES]);
}
- (void)callShowAd:(NSNumber *)mobileAdId
call:(FlutterMethodCall *)call
result:(FlutterResult)result {
FLTMobileAd *ad = [FLTMobileAd getAdForId:mobileAdId];
if (ad == nil) {
NSString *message =
[NSString stringWithFormat:@"show failed, the specified ad was not loaded id=%d",
mobileAdId.intValue];
result([FlutterError errorWithCode:@"ad_not_loaded" message:message details:nil]);
}
double offset = 0.0;
int type = 0;
if (call.arguments[@"anchorOffset"] != nil) {
offset = [call.arguments[@"anchorOffset"] doubleValue];
}
if (call.arguments[@"anchorType"] != nil) {
type = [call.arguments[@"anchorType"] isEqualToString:@"bottom"] ? 0 : 1;
}
[ad showAtOffset:offset fromAnchor:type];
result([NSNumber numberWithBool:YES]);
}
- (void)callShowRewardedVideoAd:(FlutterMethodCall *)call result:(FlutterResult)result {
if (self.rewardedWrapper.status != FLTRewardedVideoAdStatusLoaded) {
result([FlutterError errorWithCode:@"ad_not_loaded"
message:@"show failed for rewarded video, no ad was loaded"
details:nil]);
return;
}
[self.rewardedWrapper show];
result([NSNumber numberWithBool:YES]);
}
- (void)callDisposeAd:(NSNumber *)mobileAdId
call:(FlutterMethodCall *)call
result:(FlutterResult)result {
FLTMobileAd *ad = [FLTMobileAd getAdForId:mobileAdId];
if (ad == nil) {
NSString *message =
[NSString stringWithFormat:@"dispose failed, no ad exists for id=%d", mobileAdId.intValue];
result([FlutterError errorWithCode:@"no_ad_for_id" message:message details:nil]);
}
[ad dispose];
result([NSNumber numberWithBool:YES]);
}
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if ([call.method isEqualToString:@"initialize"]) {
[self callInitialize:call result:result];
return;
}
if ([call.method isEqualToString:@"loadRewardedVideoAd"]) {
[self callLoadRewardedVideoAd:call result:result];
return;
}
if ([call.method isEqualToString:@"showRewardedVideoAd"]) {
[self callShowRewardedVideoAd:call result:result];
return;
}
NSNumber *mobileAdId = (NSNumber *)call.arguments[@"id"];
if (mobileAdId == nil) {
NSString *message =
@"FirebaseAdMobPlugin method calls for banners and "
@"interstitials must specify an "
@"integer mobile ad id";
result([FlutterError errorWithCode:@"no_id" message:message details:nil]);
return;
}
if ([call.method isEqualToString:@"loadBannerAd"]) {
[self callLoadBannerAdWithId:mobileAdId channel:self.channel call:call result:result];
} else if ([call.method isEqualToString:@"loadInterstitialAd"]) {
[self callLoadInterstitialAd:[FLTInterstitialAd withId:mobileAdId channel:self.channel]
call:call
result:result];
} else if ([call.method isEqualToString:@"showAd"]) {
[self callShowAd:mobileAdId call:call result:result];
} else if ([call.method isEqualToString:@"disposeAd"]) {
[self callDisposeAd:mobileAdId call:call result:result];
} else {
result(FlutterMethodNotImplemented);
}
}
@end