adding adNetwork SDKs for AdWhirl and AdMob

This commit is contained in:
techdragon.nguyen@gmail.com
2011-12-15 11:18:37 +00:00
parent dc7d52c48c
commit 9c10f47daa
160 changed files with 23482 additions and 0 deletions
@@ -0,0 +1,46 @@
/*
ARRollerView.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "ARRollerView.h"
#import "AdWhirlView+.h"
@interface ARRollerView ()
- (id)initWithDelegate:(id<ARRollerDelegate>)delegate;
@end
@implementation ARRollerView
+ (ARRollerView*)requestRollerViewWithDelegate:(id<ARRollerDelegate>)delegate {
return [[[ARRollerView alloc] initWithDelegate:delegate] autorelease];
}
- (id)initWithDelegate:(id<ARRollerDelegate>)d {
return [super initWithDelegate:d];
}
- (void)getNextAd {
[self requestFreshAd];
}
- (void)setDelegateToNil {
self.delegate = nil;
}
@end
@@ -0,0 +1,29 @@
/*
AWNetworkReachabilityDelegate.h
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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.
*/
@class AWNetworkReachabilityWrapper;
@protocol AWNetworkReachabilityDelegate <NSObject>
@optional
- (void)reachabilityBecameReachable:(AWNetworkReachabilityWrapper *)reachability;
- (void)reachabilityNotReachable:(AWNetworkReachabilityWrapper *)reachability;
@end
@@ -0,0 +1,53 @@
/*
AWNetworkReachabilityWrapper.h
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <netdb.h>
#import "AWNetworkReachabilityDelegate.h"
@class AWNetworkReachabilityWrapper;
// Created for ease of mocking (hence testing)
@interface AWNetworkReachabilityWrapper : NSObject {
NSString *hostname_;
SCNetworkReachabilityRef reachability_;
id<AWNetworkReachabilityDelegate> delegate_;
}
@property (nonatomic,readonly) NSString *hostname;
@property (nonatomic,assign) id<AWNetworkReachabilityDelegate> delegate;
+ (AWNetworkReachabilityWrapper *) reachabilityWithHostname:(NSString *)host
callbackDelegate:(id<AWNetworkReachabilityDelegate>)delegate;
- (id)initWithHostname:(NSString *)host
callbackDelegate:(id<AWNetworkReachabilityDelegate>)delegate;
- (BOOL)scheduleInCurrentRunLoop;
- (BOOL)unscheduleFromCurrentRunLoop;
@end
@@ -0,0 +1,172 @@
/*
AWNetworkReachabilityWrapper.m
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AWNetworkReachabilityWrapper.h"
#import "AdWhirlLog.h"
static void reachabilityCallback(SCNetworkReachabilityRef reachability,
SCNetworkReachabilityFlags flags,
void* data);
@implementation AWNetworkReachabilityWrapper
@synthesize hostname = hostname_;
@synthesize delegate = delegate_;
+ (AWNetworkReachabilityWrapper *) reachabilityWithHostname:(NSString *)host
callbackDelegate:(id<AWNetworkReachabilityDelegate>)delegate {
return [[[AWNetworkReachabilityWrapper alloc] initWithHostname:host
callbackDelegate:delegate]
autorelease];
}
- (id)initWithHostname:(NSString *)host
callbackDelegate:(id<AWNetworkReachabilityDelegate>)delegate {
self = [super init];
if (self != nil) {
reachability_ = SCNetworkReachabilityCreateWithName(NULL,
[host UTF8String]);
if (reachability_ == nil) {
AWLogError(@"Error creating SCNetworkReachability");
[self release];
return nil;
}
hostname_ = [[NSString alloc] initWithString:host];
self.delegate = delegate;
// set callback
SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL};
if (!SCNetworkReachabilitySetCallback(reachability_,
&reachabilityCallback,
&context)) {
AWLogError(@"Error setting SCNetworkReachability callback");
[self release];
return nil;
}
}
return self;
}
- (BOOL)scheduleInCurrentRunLoop {
return SCNetworkReachabilityScheduleWithRunLoop(reachability_,
CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
}
- (BOOL)unscheduleFromCurrentRunLoop {
return SCNetworkReachabilityUnscheduleFromRunLoop(reachability_,
CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
}
- (void)dealloc {
[self unscheduleFromCurrentRunLoop];
if (reachability_ != NULL) CFRelease(reachability_);
[hostname_ release];
[super dealloc];
}
#pragma mark callback methods
static void printReachabilityFlags(SCNetworkReachabilityFlags flags)
{
AWLogDebug(@"Reachability flag status: %c%c%c%c%c%c%c%c%c",
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
#ifdef kSCNetworkReachabilityFlagsConnectionOnDemand
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
#else
'-',
#endif
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-',
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-'
);
}
- (void)notifyDelegateNotReachable {
if (self.delegate != nil && [self.delegate respondsToSelector:
@selector(reachabilityNotReachable:)]) {
[self.delegate reachabilityNotReachable:self];
}
}
- (void)gotCallback:(SCNetworkReachabilityRef)reachability
flags:(SCNetworkReachabilityFlags)flags {
if (reachability != reachability_) {
AWLogError(@"Unrelated reachability calling back to this object");
return;
}
printReachabilityFlags(flags);
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) {
[self notifyDelegateNotReachable];
return;
}
// even if the Reachable flag is on it may not be true for immediate use
BOOL reachable = NO;
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) {
// no connection required, we should be able to connect, via WiFi presumably
reachable = YES;
}
if ((
#ifdef kSCNetworkReachabilityFlagsConnectionOnDemand
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0 ||
#endif
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)
&& (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) {
// The connection is on-demand or on-traffic and no user intervention is
// needed, likely able to connect
reachable = YES;
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN)
== kSCNetworkReachabilityFlagsIsWWAN) {
// WWAN connections are available, likely able to connect barring network
// outage...
reachable = YES;
}
if (!reachable) {
[self notifyDelegateNotReachable];
return;
}
// notify delegate that host just got reachable
if (self.delegate != nil && [self.delegate respondsToSelector:
@selector(reachabilityBecameReachable:)]) {
[self.delegate reachabilityBecameReachable:self];
}
}
void reachabilityCallback(SCNetworkReachabilityRef reachability,
SCNetworkReachabilityFlags flags,
void* data) {
AWNetworkReachabilityWrapper *wrapper = (AWNetworkReachabilityWrapper *)data;
[wrapper gotCallback:reachability flags:flags];
}
@end
@@ -0,0 +1,46 @@
/*
AdWhirlAdNetworkAdapter+Helpers.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkAdapter.h"
@interface AdWhirlAdNetworkAdapter (Helpers)
/**
* Subclasses call this to notify delegate that there's going to be a full
* screen modal (usually after tap).
*/
- (void)helperNotifyDelegateOfFullScreenModal;
/**
* Subclasses call this to notify delegate that the full screen modal has
* been dismissed.
*/
- (void)helperNotifyDelegateOfFullScreenModalDismissal;
/*
* Subclasses call to get various configs to use, from the AdWhirlDelegate or
* config from server.
*/
- (UIColor *)helperBackgroundColorToUse;
- (UIColor *)helperTextColorToUse;
- (UIColor *)helperSecondaryTextColorToUse;
- (NSInteger)helperCalculateAge;
@end
@@ -0,0 +1,93 @@
/*
AdWhirlAdNetworkAdapter+Helpers.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkAdapter+Helpers.h"
#import "AdWhirlView.h"
#import "AdWhirlView+.h"
#import "AdWhirlConfig.h"
#import "AdWhirlAdNetworkConfig.h"
@implementation AdWhirlAdNetworkAdapter (Helpers)
- (void)helperNotifyDelegateOfFullScreenModal {
// don't request new ad when modal view is on
adWhirlView.showingModalView = YES;
if ([adWhirlDelegate respondsToSelector:@selector(adWhirlWillPresentFullScreenModal)]) {
[adWhirlDelegate adWhirlWillPresentFullScreenModal];
}
}
- (void)helperNotifyDelegateOfFullScreenModalDismissal {
if ([adWhirlDelegate respondsToSelector:@selector(adWhirlDidDismissFullScreenModal)]) {
[adWhirlDelegate adWhirlDidDismissFullScreenModal];
}
adWhirlView.showingModalView = NO;
}
- (UIColor *)helperBackgroundColorToUse {
if ([adWhirlDelegate respondsToSelector:@selector(adWhirlAdBackgroundColor)]) {
UIColor *color = [adWhirlDelegate adWhirlAdBackgroundColor];
if (color != nil) return color;
}
if ([adWhirlDelegate respondsToSelector:@selector(backgroundColor)]) {
UIColor *color = [adWhirlDelegate backgroundColor];
if (color != nil) return color;
}
return adWhirlConfig.backgroundColor;
}
- (UIColor *)helperTextColorToUse {
if ([adWhirlDelegate respondsToSelector:@selector(adWhirlTextColor)]) {
UIColor *color = [adWhirlDelegate adWhirlTextColor];
if (color != nil) return color;
}
if ([adWhirlDelegate respondsToSelector:@selector(textColor)]) {
UIColor *color = [adWhirlDelegate textColor];
if (color != nil) return color;
}
return adWhirlConfig.textColor;
}
- (UIColor *)helperSecondaryTextColorToUse {
if ([adWhirlDelegate respondsToSelector:@selector(adWhirlSecondaryTextColor)]) {
UIColor *color = [adWhirlDelegate adWhirlSecondaryTextColor];
if (color != nil) return color;
}
return nil;
}
- (NSInteger)helperCalculateAge {
NSDate *birth = [adWhirlDelegate dateOfBirth];
if (birth == nil) {
return -1;
}
NSDate *today = [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:NSYearCalendarUnit
fromDate:birth
toDate:today
options:0];
NSInteger years = [components year];
[gregorian release];
[today release];
return years;
}
@end
@@ -0,0 +1,84 @@
/*
AdWhirlAdNetworkAdapter.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkAdapter.h"
#import "AdWhirlView.h"
#import "AdWhirlConfig.h"
#import "AdWhirlAdNetworkConfig.h"
#import "AdWhirlLog.h"
#import "AdWhirlAdNetworkRegistry.h"
@implementation AdWhirlAdNetworkAdapter
@synthesize adWhirlDelegate;
@synthesize adWhirlView;
@synthesize adWhirlConfig;
@synthesize networkConfig;
@synthesize adNetworkView;
- (id)initWithAdWhirlDelegate:(id<AdWhirlDelegate>)delegate
view:(AdWhirlView *)view
config:(AdWhirlConfig *)config
networkConfig:(AdWhirlAdNetworkConfig *)netConf {
self = [super init];
if (self != nil) {
self.adWhirlDelegate = delegate;
self.adWhirlView = view;
self.adWhirlConfig = config;
self.networkConfig = netConf;
}
return self;
}
- (void)getAd {
AWLogCrit(@"Subclass of AdWhirlAdNetworkAdapter must implement -getAd.");
[self doesNotRecognizeSelector:_cmd];
}
- (void)stopBeingDelegate {
AWLogCrit(@"Subclass of AdWhirlAdNetworkAdapter must implement -stopBeingDelegate.");
[self doesNotRecognizeSelector:_cmd];
}
- (BOOL)shouldSendExMetric {
return YES;
}
- (void)rotateToOrientation:(UIInterfaceOrientation)orientation {
// do nothing by default. Subclasses implement specific handling.
AWLogDebug(@"rotate to orientation %d called for adapter %@",
orientation, NSStringFromClass([self class]));
}
- (BOOL)isBannerAnimationOK:(AWBannerAnimationType)animType {
return YES;
}
- (void)dealloc {
[self stopBeingDelegate];
adWhirlDelegate = nil;
adWhirlView = nil;
[adWhirlConfig release], adWhirlConfig = nil;
[networkConfig release], networkConfig = nil;
[adNetworkView release], adNetworkView = nil;
[super dealloc];
}
@end
@@ -0,0 +1,57 @@
/*
AdNetwork.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
#import "AdWhirlDelegateProtocol.h"
#define AWAdNetworkConfigKeyType @"type"
#define AWAdNetworkConfigKeyNID @"nid"
#define AWAdNetworkConfigKeyName @"nname"
#define AWAdNetworkConfigKeyWeight @"weight"
#define AWAdNetworkConfigKeyPriority @"priority"
#define AWAdNetworkConfigKeyCred @"key"
@class AdWhirlError;
@class AdWhirlAdNetworkRegistry;
@interface AdWhirlAdNetworkConfig : NSObject {
NSInteger networkType;
NSString *nid;
NSString *networkName;
double trafficPercentage;
NSInteger priority;
NSDictionary *credentials;
Class adapterClass;
}
- (id)initWithDictionary:(NSDictionary *)adNetConfigDict
adNetworkRegistry:(AdWhirlAdNetworkRegistry *)registry
error:(AdWhirlError **)error;
@property (nonatomic,readonly) NSInteger networkType;
@property (nonatomic,readonly) NSString *nid;
@property (nonatomic,readonly) NSString *networkName;
@property (nonatomic,readonly) double trafficPercentage;
@property (nonatomic,readonly) NSInteger priority;
@property (nonatomic,readonly) NSDictionary *credentials;
@property (nonatomic,readonly) NSString *pubId;
@property (nonatomic,readonly) Class adapterClass;
@end
@@ -0,0 +1,169 @@
/*
AdNetwork.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkConfig.h"
#import "AdWhirlConfig.h"
#import "AdWhirlAdNetworkRegistry.h"
#import "AdWhirlLog.h"
#import "AdWhirlError.h"
#import "AdWhirlClassWrapper.h"
#define kAdWhirlPubIdKey @"pubid"
@implementation AdWhirlAdNetworkConfig
@synthesize networkType;
@synthesize nid;
@synthesize networkName;
@synthesize trafficPercentage;
@synthesize priority;
@synthesize credentials;
@synthesize adapterClass;
- (id)initWithDictionary:(NSDictionary *)adNetConfigDict
adNetworkRegistry:(AdWhirlAdNetworkRegistry *)registry
error:(AdWhirlError **)error {
self = [super init];
if (self != nil) {
NSInteger temp;
id ntype = [adNetConfigDict objectForKey:AWAdNetworkConfigKeyType];
id netId = [adNetConfigDict objectForKey:AWAdNetworkConfigKeyNID];
id netName = [adNetConfigDict objectForKey:AWAdNetworkConfigKeyName];
id weight = [adNetConfigDict objectForKey:AWAdNetworkConfigKeyWeight];
id pri = [adNetConfigDict objectForKey:AWAdNetworkConfigKeyPriority];
if (ntype == nil || netId == nil || netName == nil || pri == nil) {
NSString *errorMsg =
@"Ad network config has no network type, network id, network name, or priority";
if (error != nil) {
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:errorMsg];
}
else {
AWLogWarn(errorMsg);
}
[self release];
return nil;
}
if (awIntVal(&temp, ntype)) {
networkType = temp;
}
if ([netId isKindOfClass:[NSString class]]) {
nid = [[NSString alloc] initWithString:netId];
}
if ([netName isKindOfClass:[NSString class]]) {
networkName = [[NSString alloc] initWithString:netName];
}
double tempDouble;
if (weight == nil) {
trafficPercentage = 0.0;
}
else if (awDoubleVal(&tempDouble, weight)) {
trafficPercentage = tempDouble;
}
if (awIntVal(&temp, pri)) {
priority = temp;
}
if (networkType == 0 || nid == nil || networkName == nil || priority == 0) {
NSString *errorMsg =
@"Ad network config has invalid network type, network id, network name or priority";
if (error != nil) {
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:errorMsg];
}
else {
AWLogWarn(errorMsg);
}
[self release];
return nil;
}
id cred = [adNetConfigDict objectForKey:AWAdNetworkConfigKeyCred];
if (cred == nil) {
credentials = nil;
}
else {
if ([cred isKindOfClass:[NSDictionary class]]) {
credentials = [[NSDictionary alloc] initWithDictionary:cred copyItems:YES];
}
else if ([cred isKindOfClass:[NSString class]]) {
credentials = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSString stringWithString:cred], kAdWhirlPubIdKey,
nil];
}
}
adapterClass = [registry adapterClassFor:networkType].theClass;
if (adapterClass == nil) {
NSString *errorMsg =
[NSString stringWithFormat:@"Ad network type %d not supported, no adapter found",
networkType];
if (error != nil) {
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:errorMsg];
}
else {
AWLogWarn(errorMsg);
}
[self release];
return nil;
}
}
return self;
}
- (NSString *)pubId {
if (credentials == nil) return nil;
return [credentials objectForKey:kAdWhirlPubIdKey];
}
- (NSString *)description {
NSString *creds = [self pubId];
if (creds == nil) {
creds = @"{";
for (NSString *k in [credentials keyEnumerator]) {
creds = [creds stringByAppendingFormat:@"%@:%@ ",
k, [credentials objectForKey:k]];
}
creds = [creds stringByAppendingString:@"}"];
}
return [NSString stringWithFormat:
@"name:%@ type:%d nid:%@ weight:%lf priority:%d creds:%@",
networkName, networkType, nid, trafficPercentage, priority, creds];
}
- (void)dealloc {
[nid release], nid = nil;
[networkName release], networkName = nil;
[credentials release], credentials = nil;
[super dealloc];
}
@end
@@ -0,0 +1,34 @@
/*
AdWhirlAdNetworkRegistry.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
@class AdWhirlAdNetworkAdapter;
@class AdWhirlClassWrapper;
@interface AdWhirlAdNetworkRegistry : NSObject {
NSMutableDictionary *adapterDict;
}
+ (AdWhirlAdNetworkRegistry *)sharedRegistry;
- (void)registerClass:(Class)adapterClass;
- (AdWhirlClassWrapper *)adapterClassFor:(NSInteger)adNetworkType;
@end
@@ -0,0 +1,64 @@
/*
AdWhirlAdNetworkRegistry.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkRegistry.h"
#import "AdWhirlAdNetworkAdapter.h"
#import "AdWhirlClassWrapper.h"
@implementation AdWhirlAdNetworkRegistry
+ (AdWhirlAdNetworkRegistry *)sharedRegistry {
static AdWhirlAdNetworkRegistry *registry = nil;
if (registry == nil) {
registry = [[AdWhirlAdNetworkRegistry alloc] init];
}
return registry;
}
- (id)init {
self = [super init];
if (self != nil) {
adapterDict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)registerClass:(Class)adapterClass {
// have to do all these to avoid compiler warnings...
NSInteger (*netTypeMethod)(id, SEL);
netTypeMethod = (NSInteger (*)(id, SEL))[adapterClass methodForSelector:@selector(networkType)];
NSInteger netType = netTypeMethod(adapterClass, @selector(networkType));
NSNumber *key = [[NSNumber alloc] initWithInteger:netType];
AdWhirlClassWrapper *wrapper = [[AdWhirlClassWrapper alloc] initWithClass:adapterClass];
[adapterDict setObject:wrapper forKey:key];
[key release];
[wrapper release];
}
- (AdWhirlClassWrapper *)adapterClassFor:(NSInteger)adNetworkType {
return [adapterDict objectForKey:[NSNumber numberWithInteger:adNetworkType]];
}
- (void)dealloc {
[adapterDict release], adapterDict = nil;
[super dealloc];
}
@end
@@ -0,0 +1,40 @@
/*
AdWhirlAdapterCustom.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkAdapter.h"
#import "AdWhirlCustomAdView.h"
#import "AdWhirlWebBrowserController.h"
@interface AdWhirlAdapterCustom : AdWhirlAdNetworkAdapter <AdWhirlCustomAdViewDelegate,
AdWhirlWebBrowserControllerDelegate>
{
BOOL requesting;
CLLocationManager *locationManager;
NSURLConnection *adConnection;
NSMutableData *adData;
NSURLConnection *imageConnection;
NSMutableData *imageData;
AdWhirlCustomAdView *adView;
AdWhirlWebBrowserController *webBrowserController;
}
+ (AdWhirlAdNetworkType)networkType;
@end
@@ -0,0 +1,423 @@
/*
AdWhirlAdapterCustom.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdapterCustom.h"
#import "AdWhirlView.h"
#import "AdWhirlLog.h"
#import "AdWhirlConfig.h"
#import "AdWhirlAdNetworkConfig.h"
#import "AdWhirlError.h"
#import "CJSONDeserializer.h"
#import "AdWhirlCustomAdView.h"
#import "AdWhirlAdNetworkAdapter+Helpers.h"
#import "AdWhirlAdNetworkRegistry.h"
@interface AdWhirlAdapterCustom ()
- (BOOL)parseAdData:(NSData *)data error:(NSError **)error;
@property (nonatomic,readonly) CLLocationManager *locationManager;
@property (nonatomic,retain) NSURLConnection *adConnection;
@property (nonatomic,retain) NSURLConnection *imageConnection;
@property (nonatomic,retain) AdWhirlCustomAdView *adView;
@property (nonatomic,retain) AdWhirlWebBrowserController *webBrowserController;
@property (nonatomic, assign) CGFloat scale;
@end
@implementation AdWhirlAdapterCustom
@synthesize adConnection;
@synthesize imageConnection;
@synthesize adView;
@synthesize webBrowserController;
@synthesize scale;
+ (AdWhirlAdNetworkType)networkType {
return AdWhirlAdNetworkTypeCustom;
}
+ (void)load {
[[AdWhirlAdNetworkRegistry sharedRegistry] registerClass:self];
}
- (id)initWithAdWhirlDelegate:(id<AdWhirlDelegate>)delegate
view:(AdWhirlView *)view
config:(AdWhirlConfig *)config
networkConfig:(AdWhirlAdNetworkConfig *)netConf {
self = [super initWithAdWhirlDelegate:delegate
view:view
config:config
networkConfig:netConf];
if (self != nil) {
adData = [[NSMutableData alloc] init];
imageData = [[NSMutableData alloc] init];
}
return self;
}
- (BOOL)shouldSendExMetric {
return NO; // since we are getting the ad from the AdWhirl server anyway, no
// need to send extra metric ping to the same server.
}
- (void)getAd {
@synchronized(self) {
if (requesting) return;
requesting = YES;
}
NSURL *adRequestBaseURL = nil;
if ([self.adWhirlDelegate respondsToSelector:@selector(adWhirlCustomAdURL)]) {
adRequestBaseURL = [self.adWhirlDelegate adWhirlCustomAdURL];
}
if (adRequestBaseURL == nil) {
adRequestBaseURL = [NSURL URLWithString:kAdWhirlDefaultCustomAdURL];
}
NSString *query;
if (self.adWhirlConfig.locationOn) {
AWLogDebug(@"Allow location access in custom ad");
CLLocation *location;
if ([self.adWhirlDelegate respondsToSelector:@selector(locationInfo)]) {
location = [self.adWhirlDelegate locationInfo];
}
else {
location = [self.locationManager location];
}
NSString *locationStr = [NSString stringWithFormat:@"%lf,%lf",
location.coordinate.latitude,
location.coordinate.longitude];
query = [NSString stringWithFormat:@"?appver=%d&country_code=%@&appid=%@&nid=%@&location=%@&location_timestamp=%lf&client=1",
kAdWhirlAppVer,
[[NSLocale currentLocale] localeIdentifier],
self.adWhirlConfig.appKey,
self.networkConfig.nid,
locationStr,
[[NSDate date] timeIntervalSince1970]];
}
else {
AWLogDebug(@"Do not allow location access in custom ad");
query = [NSString stringWithFormat:@"?appver=%d&country_code=%@&appid=%@&nid=%@&client=1",
kAdWhirlAppVer,
[[NSLocale currentLocale] localeIdentifier],
self.adWhirlConfig.appKey,
self.networkConfig.nid];
}
NSURL *adRequestURL = [NSURL URLWithString:query relativeToURL:adRequestBaseURL];
AWLogDebug(@"Requesting custom ad at %@", adRequestURL);
NSURLRequest *adRequest = [NSURLRequest requestWithURL:adRequestURL];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:adRequest
delegate:self];
self.adConnection = conn;
[conn release];
}
- (void)stopBeingDelegate {
AdWhirlCustomAdView *theAdView = (AdWhirlCustomAdView *)self.adNetworkView;
if (theAdView != nil) {
theAdView.delegate = nil;
}
}
- (void)dealloc {
[locationManager release], locationManager = nil;
[adConnection release], adConnection = nil;
[adData release], adData = nil;
[imageConnection release], imageConnection = nil;
[imageData release], imageData = nil;
[adView release], adView = nil;
[webBrowserController release], webBrowserController = nil;
[super dealloc];
}
- (CLLocationManager *)locationManager {
if (locationManager == nil) {
locationManager = [[CLLocationManager alloc] init];
}
return locationManager;
}
- (BOOL)parseEnums:(int *)val
adInfo:(NSDictionary*)info
minVal:(int)min
maxVal:(int)max
fieldName:(NSString *)name
error:(NSError **)error {
NSString *str = [info objectForKey:name];
if (str == nil) {
if (error != nil)
*error = [AdWhirlError errorWithCode:AdWhirlCustomAdDataError
description:[NSString stringWithFormat:
@"Custom ad data has no '%@' field", name]];
return NO;
}
int intVal = [str intValue];
if (intVal <= min || intVal >= max) {
if (error != nil)
*error = [AdWhirlError errorWithCode:AdWhirlCustomAdDataError
description:[NSString stringWithFormat:
@"Custom ad: Invalid value for %@ - %d", name, intVal]];
return NO;
}
*val = intVal;
return YES;
}
- (BOOL)parseAdData:(NSData *)data error:(NSError **)error {
NSError *jsonError = nil;
id parsed = [[CJSONDeserializer deserializer] deserialize:data error:&jsonError];
if (parsed == nil) {
if (error != nil)
*error = [AdWhirlError errorWithCode:AdWhirlCustomAdParseError
description:@"Error parsing custom ad JSON from server"
underlyingError:jsonError];
return NO;
}
if ([parsed isKindOfClass:[NSDictionary class]]) {
NSDictionary *adInfo = parsed;
// gather up and validate ad info
NSString *text = [adInfo objectForKey:@"ad_text"];
NSString *redirectURLStr = [adInfo objectForKey:@"redirect_url"];
int adTypeInt;
if (![self parseEnums:&adTypeInt
adInfo:adInfo
minVal:AWCustomAdTypeMIN
maxVal:AWCustomAdTypeMAX
fieldName:@"ad_type"
error:error]) {
return NO;
}
AWCustomAdType adType = adTypeInt;
int launchTypeInt;
if (![self parseEnums:&launchTypeInt
adInfo:adInfo
minVal:AWCustomAdLaunchTypeMIN
maxVal:AWCustomAdLaunchTypeMAX
fieldName:@"launch_type"
error:error]) {
return NO;
}
AWCustomAdLaunchType launchType = launchTypeInt;
int animTypeInt;
if (![self parseEnums:&animTypeInt
adInfo:adInfo
minVal:AWCustomAdWebViewAnimTypeMIN
maxVal:AWCustomAdWebViewAnimTypeMAX
fieldName:@"webview_animation_type"
error:error]) {
return NO;
}
AWCustomAdWebViewAnimType animType = animTypeInt;
NSURL *redirectURL = nil;
if (redirectURLStr == nil) {
AWLogWarn(@"No redirect URL for custom ad");
}
else {
redirectURL = [[NSURL alloc] initWithString:redirectURLStr];
if (!redirectURL)
AWLogWarn(@"Custom ad: Malformed redirect URL string %@", redirectURLStr);
}
NSString *clickMetricsURLStr = [adInfo objectForKey:@"metrics_url"];
NSURL *clickMetricsURL = nil;
if (clickMetricsURLStr == nil) {
AWLogWarn(@"No click metric URL for custom ad");
}
else {
clickMetricsURL = [[NSURL alloc] initWithString:clickMetricsURLStr];
if (!clickMetricsURL)
AWLogWarn(@"Malformed click metrics URL string %@", clickMetricsURLStr);
}
AWLogDebug(@"Got custom ad '%@' %@ %@ %d %d %d", text, redirectURL,
clickMetricsURL, adType, launchType, animType);
self.adView = [[AdWhirlCustomAdView alloc] initWithDelegate:self
text:text
redirectURL:redirectURL
clickMetricsURL:clickMetricsURL
adType:adType
launchType:launchType
animType:animType
backgroundColor:[self helperBackgroundColorToUse]
textColor:[self helperTextColorToUse]];
[self.adView release];
self.adNetworkView = adView;
[redirectURL release];
[clickMetricsURL release];
if (adView == nil) {
if (error != nil)
*error = [AdWhirlError errorWithCode:AdWhirlCustomAdDataError
description:@"Error initializing AdWhirl custom ad view"];
return NO;
}
// fetch image, set scale
self.scale = [[UIScreen mainScreen] respondsToSelector:@selector(scale)] ? [[UIScreen mainScreen] scale] : 1.0;
NSString *imageURL;
if (self.scale == 2.0 && adType == AWCustomAdTypeBanner) {
imageURL = [adInfo objectForKey:@"img_url_640x100"];
if (imageURL == nil || [imageURL length] == 0) {
self.scale = 1.0f;
imageURL = [adInfo objectForKey:@"img_url"];
}
} else {
imageURL = [adInfo objectForKey:@"img_url"];
}
AWLogDebug(@"Request custom ad image at %@", imageURL);
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURL]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:imageRequest
delegate:self];
self.imageConnection = conn;
[conn release];
}
else {
if (error != nil)
*error = [AdWhirlError errorWithCode:AdWhirlCustomAdDataError
description:@"Expected top-level dictionary in custom ad data"];
return NO;
}
return YES;
}
#pragma mark NSURLConnection delegate methods.
- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response {
if (conn == adConnection) {
[adData setLength:0];
}
else if (conn == imageConnection) {
[imageData setLength:0];
}
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error {
if (conn == adConnection) {
[self.adWhirlView adapter:self didFailAd:[AdWhirlError errorWithCode:AdWhirlCustomAdConnectionError
description:@"Error connecting to custom ad server"
underlyingError:error]];
requesting = NO;
}
else if (conn == imageConnection) {
[self.adWhirlView adapter:self didFailAd:[AdWhirlError errorWithCode:AdWhirlCustomAdConnectionError
description:@"Error connecting to custom ad server to fetch image"
underlyingError:error]];
requesting = NO;
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn {
if (conn == adConnection) {
NSError *error = nil;
if (![self parseAdData:adData error:&error]) {
[self.adWhirlView adapter:self didFailAd:error];
requesting = NO;
return;
}
}
else if (conn == imageConnection) {
UIImage *image = [[UIImage alloc] initWithData:imageData];
if (self.scale == 2.0) {
UIImage *img = [[UIImage alloc] initWithCGImage:image.CGImage scale:2.0 orientation:image.imageOrientation];
[image release];
image = img;
}
if (image == nil) {
[self.adWhirlView adapter:self didFailAd:[AdWhirlError errorWithCode:AdWhirlCustomAdImageError
description:@"Cannot initialize custom ad image from data"]];
requesting = NO;
return;
}
adView.image = image;
[adView setNeedsDisplay];
[image release];
requesting = NO;
[self.adWhirlView adapter:self didReceiveAdView:self.adView];
}
}
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data {
if (conn == adConnection) {
[adData appendData:data];
}
else if (conn == imageConnection) {
[imageData appendData:data];
}
}
#pragma mark AdWhirlCustomAdViewDelegate methods
- (void)adTapped:(AdWhirlCustomAdView *)ad {
if (ad != adView) return;
if (ad.clickMetricsURL != nil) {
NSURLRequest *metRequest = [NSURLRequest requestWithURL:ad.clickMetricsURL];
[NSURLConnection connectionWithRequest:metRequest
delegate:nil]; // fire and forget
AWLogDebug(@"Sent custom ad click ping to %@", ad.clickMetricsURL);
}
if (ad.redirectURL == nil) {
AWLogError(@"Custom ad redirect URL is nil");
return;
}
switch (ad.launchType) {
case AWCustomAdLaunchTypeSafari:
AWLogDebug(@"Opening URL '%@' for custom ad", ad.redirectURL);
if ([[UIApplication sharedApplication] openURL:ad.redirectURL] == NO) {
AWLogError(@"Cannot open URL '%@' for custom ad", ad.redirectURL);
}
break;
case AWCustomAdLaunchTypeCanvas:
if (self.webBrowserController == nil) {
AdWhirlWebBrowserController *ctrlr = [[AdWhirlWebBrowserController alloc] init];
self.webBrowserController = ctrlr;
[ctrlr release];
}
webBrowserController.delegate = self;
[webBrowserController presentWithController:[self.adWhirlDelegate viewControllerForPresentingModalView]
transition:ad.animType];
[self helperNotifyDelegateOfFullScreenModal];
[webBrowserController loadURL:ad.redirectURL];
break;
default:
AWLogError(@"Custom ad: Unsupported launch type %d", ad.launchType);
break;
}
}
#pragma mark AdWhirlWebBrowserControllerDelegate methods
- (void)webBrowserClosed:(AdWhirlWebBrowserController *)controller {
if (controller != webBrowserController) return;
self.webBrowserController = nil; // don't keep around to save memory
[self helperNotifyDelegateOfFullScreenModalDismissal];
}
@end
@@ -0,0 +1,29 @@
/*
AdWhirlAdapterEvent.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkAdapter.h"
@interface AdWhirlAdapterEvent : AdWhirlAdNetworkAdapter {
}
+ (AdWhirlAdNetworkType)networkType;
@end
@@ -0,0 +1,69 @@
/*
AdWhirlAdapterEvent.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdapterEvent.h"
#import "AdWhirlView.h"
#import "AdWhirlLog.h"
#import "AdWhirlAdNetworkAdapter+Helpers.h"
#import "AdWhirlAdNetworkRegistry.h"
#import "AdWhirlAdNetworkConfig.h"
@implementation AdWhirlAdapterEvent
+ (AdWhirlAdNetworkType)networkType {
return AdWhirlAdNetworkTypeEvent;
}
+ (void)load {
[[AdWhirlAdNetworkRegistry sharedRegistry] registerClass:self];
}
- (void)getAd {
NSArray *eventKeys = [networkConfig.pubId componentsSeparatedByString:@"|;|"];
NSString *eventSelectorStr = [eventKeys objectAtIndex:1];
SEL eventSelector = NSSelectorFromString(eventSelectorStr);
if ([adWhirlDelegate respondsToSelector:eventSelector]) {
[adWhirlDelegate performSelector:eventSelector];
[adWhirlView adapterDidFinishAdRequest:self];
}
else {
NSString *eventSelectorColonStr = [NSString stringWithFormat:@"%@:", eventSelectorStr];
SEL eventSelectorColon = NSSelectorFromString(eventSelectorColonStr);
if ([adWhirlDelegate respondsToSelector:eventSelectorColon]) {
[adWhirlDelegate performSelector:eventSelectorColon withObject:adWhirlView];
[adWhirlView adapterDidFinishAdRequest:self];
}
else {
AWLogWarn(@"Delegate does not implement function %@ nor %@", eventSelectorStr, eventSelectorColonStr);
[adWhirlView adapter:self didFailAd:nil];
}
}
}
- (void)stopBeingDelegate {
// Nothing to do
}
- (void)dealloc {
[super dealloc];
}
@end
@@ -0,0 +1,29 @@
/*
AdWhirlAdapterGeneric.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkAdapter.h"
@interface AdWhirlAdapterGeneric : AdWhirlAdNetworkAdapter {
}
+ (AdWhirlAdNetworkType)networkType;
@end
@@ -0,0 +1,56 @@
/*
AdWhirlAdapterGeneric.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdapterGeneric.h"
#import "AdWhirlView.h"
#import "AdWhirlLog.h"
#import "AdWhirlAdNetworkAdapter+Helpers.h"
#import "AdWhirlAdNetworkRegistry.h"
@implementation AdWhirlAdapterGeneric
+ (AdWhirlAdNetworkType)networkType {
return AdWhirlAdNetworkTypeGeneric;
}
+ (void)load {
[[AdWhirlAdNetworkRegistry sharedRegistry] registerClass:self];
}
- (void)getAd {
if ([adWhirlDelegate respondsToSelector:@selector(adWhirlReceivedRequestForDeveloperToFufill:)]) {
[adWhirlDelegate adWhirlReceivedRequestForDeveloperToFufill:adWhirlView];
[adWhirlView adapterDidFinishAdRequest:self];
}
else {
AWLogWarn(@"Delegate does not implement adWhirlReceivedRequestForDeveloperToFufill");
[adWhirlView adapter:self didFailAd:nil];
}
}
- (void)stopBeingDelegate {
// nothing to do
}
- (void)dealloc {
[super dealloc];
}
@end
@@ -0,0 +1,31 @@
/*
AdWhirlClassWrapper.h
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
@interface AdWhirlClassWrapper : NSObject {
Class theClass;
}
- (id)initWithClass:(Class)c;
@property (nonatomic, readonly) Class theClass;
@end
@@ -0,0 +1,35 @@
/*
AdWhirlClassWrapper.m
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlClassWrapper.h"
@implementation AdWhirlClassWrapper
@synthesize theClass;
- (id)initWithClass:(Class)c {
self = [super init];
if (self != nil) {
theClass = c;
}
return self;
}
@end
@@ -0,0 +1,103 @@
/*
AdWhirlConfig.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "CJSONDeserializer.h"
@class AdWhirlConfig;
@protocol AdWhirlConfigDelegate<NSObject>
@optional
- (void)adWhirlConfigDidReceiveConfig:(AdWhirlConfig *)config;
- (void)adWhirlConfigDidFail:(AdWhirlConfig *)config error:(NSError *)error;
- (NSURL *)adWhirlConfigURL;
@end
typedef enum {
AWBannerAnimationTypeNone = 0,
AWBannerAnimationTypeFlipFromLeft = 1,
AWBannerAnimationTypeFlipFromRight = 2,
AWBannerAnimationTypeCurlUp = 3,
AWBannerAnimationTypeCurlDown = 4,
AWBannerAnimationTypeSlideFromLeft = 5,
AWBannerAnimationTypeSlideFromRight = 6,
AWBannerAnimationTypeFadeIn = 7,
AWBannerAnimationTypeRandom = 8,
} AWBannerAnimationType;
@class AdWhirlAdNetworkConfig;
@class AdWhirlAdNetworkRegistry;
@interface AdWhirlConfig : NSObject {
NSString *appKey;
NSURL *configURL;
BOOL legacy;
BOOL adsAreOff;
NSMutableArray *adNetworkConfigs;
UIColor *backgroundColor;
UIColor *textColor;
NSTimeInterval refreshInterval;
BOOL locationOn;
AWBannerAnimationType bannerAnimationType;
NSInteger fullscreenWaitInterval;
NSInteger fullscreenMaxAds;
NSMutableArray *delegates;
BOOL hasConfig;
AdWhirlAdNetworkRegistry *adNetworkRegistry;
}
- (id)initWithAppKey:(NSString *)ak delegate:(id<AdWhirlConfigDelegate>)delegate;
- (BOOL)parseConfig:(NSData *)data error:(NSError **)error;
- (BOOL)addDelegate:(id<AdWhirlConfigDelegate>)delegate;
- (BOOL)removeDelegate:(id<AdWhirlConfigDelegate>)delegate;
- (void)notifyDelegatesOfFailure:(NSError *)error;
@property (nonatomic,readonly) NSString *appKey;
@property (nonatomic,readonly) NSURL *configURL;
@property (nonatomic,readonly) BOOL hasConfig;
@property (nonatomic,readonly) BOOL adsAreOff;
@property (nonatomic,readonly) NSArray *adNetworkConfigs;
@property (nonatomic,readonly) UIColor *backgroundColor;
@property (nonatomic,readonly) UIColor *textColor;
@property (nonatomic,readonly) NSTimeInterval refreshInterval;
@property (nonatomic,readonly) BOOL locationOn;
@property (nonatomic,readonly) AWBannerAnimationType bannerAnimationType;
@property (nonatomic,readonly) NSInteger fullscreenWaitInterval;
@property (nonatomic,readonly) NSInteger fullscreenMaxAds;
@property (nonatomic,assign) AdWhirlAdNetworkRegistry *adNetworkRegistry;
@end
// Convenience conversion functions, converts val into native types var.
// val can be NSNumber or NSString, all else will cause function to fail
// On failure, return NO.
BOOL awIntVal(NSInteger *var, id val);
BOOL awFloatVal(CGFloat *var, id val);
BOOL awDoubleVal(double *var, id val);
@@ -0,0 +1,562 @@
/*
AdWhirlConfig.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <CommonCrypto/CommonDigest.h>
#import "AdWhirlConfig.h"
#import "AdWhirlError.h"
#import "AdWhirlAdNetworkConfig.h"
#import "AdWhirlLog.h"
#import "AdWhirlView.h"
#import "AdWhirlAdNetworkAdapter.h"
#import "AdWhirlAdNetworkRegistry.h"
#import "UIColor+AdWhirlConfig.h"
#import "AWNetworkReachabilityWrapper.h"
BOOL awIntVal(NSInteger *var, id val) {
if ([val isKindOfClass:[NSNumber class]] || [val isKindOfClass:[NSString class]]) {
*var = [val integerValue];
return YES;
}
return NO;
}
BOOL awFloatVal(CGFloat *var, id val) {
if ([val isKindOfClass:[NSNumber class]] || [val isKindOfClass:[NSString class]]) {
*var = [val floatValue];
return YES;
}
return NO;
}
BOOL awDoubleVal(double *var, id val) {
if ([val isKindOfClass:[NSNumber class]] || [val isKindOfClass:[NSString class]]) {
*var = [val doubleValue];
return YES;
}
return NO;
}
@implementation AdWhirlConfig
@synthesize appKey;
@synthesize configURL;
@synthesize adsAreOff;
@synthesize adNetworkConfigs;
@synthesize backgroundColor;
@synthesize textColor;
@synthesize refreshInterval;
@synthesize locationOn;
@synthesize bannerAnimationType;
@synthesize fullscreenWaitInterval;
@synthesize fullscreenMaxAds;
@synthesize hasConfig;
@synthesize adNetworkRegistry;
#pragma mark -
- (id)initWithAppKey:(NSString *)ak delegate:(id<AdWhirlConfigDelegate>)delegate {
self = [super init];
if (self != nil) {
appKey = [[NSString alloc] initWithString:ak];
legacy = NO;
adNetworkConfigs = [[NSMutableArray alloc] init];
delegates = [[NSMutableArray alloc] init];
hasConfig = NO;
[self addDelegate:delegate];
// object dependencies
adNetworkRegistry = [AdWhirlAdNetworkRegistry sharedRegistry];
// default values
backgroundColor = [[UIColor alloc] initWithRed:0.3 green:0.3 blue:0.3 alpha:1.0];
textColor = [[UIColor whiteColor] retain];
refreshInterval = 60;
locationOn = YES;
bannerAnimationType = AWBannerAnimationTypeRandom;
fullscreenWaitInterval = 60;
fullscreenMaxAds = 2;
// config URL
NSURL *configBaseURL = nil;
if ([delegate respondsToSelector:@selector(adWhirlConfigURL)]) {
configBaseURL = [delegate adWhirlConfigURL];
}
if (configBaseURL == nil) {
configBaseURL = [NSURL URLWithString:kAdWhirlDefaultConfigURL];
}
configURL = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"?appid=%@&appver=%d&client=1",
appKey,
kAdWhirlAppVer]
relativeToURL:configBaseURL];
}
return self;
}
- (BOOL)addDelegate:(id<AdWhirlConfigDelegate>)delegate {
for (NSValue *w in delegates) {
id<AdWhirlConfigDelegate> existing = [w nonretainedObjectValue];
if (existing == delegate) {
return NO; // already in the list of delegates
}
}
NSValue *wrapped = [NSValue valueWithNonretainedObject:delegate];
[delegates addObject:wrapped];
return YES;
}
- (BOOL)removeDelegate:(id<AdWhirlConfigDelegate>)delegate {
NSUInteger i;
for (i = 0; i < [delegates count]; i++) {
NSValue *w = [delegates objectAtIndex:i];
id<AdWhirlConfigDelegate> existing = [w nonretainedObjectValue];
if (existing == delegate) {
break;
}
}
if (i < [delegates count]) {
[delegates removeObjectAtIndex:i];
return YES;
}
return NO;
}
- (void)notifyDelegatesOfFailure:(NSError *)error {
for (NSValue *wrapped in delegates) {
id<AdWhirlConfigDelegate> delegate = [wrapped nonretainedObjectValue];
if ([delegate respondsToSelector:@selector(adWhirlConfigDidFail:error:)]) {
[delegate adWhirlConfigDidFail:self error:error];
}
}
}
- (NSString *)description {
NSString *desc = [super description];
NSString *configs = [NSString stringWithFormat:
@"location_access:%d fg_color:%@ bg_color:%@ cycle_time:%lf transition:%d",
locationOn, textColor, backgroundColor, refreshInterval, bannerAnimationType];
return [NSString stringWithFormat:@"%@:\n%@ networks:%@",desc,configs,adNetworkConfigs];
}
- (void)dealloc {
[appKey release], appKey = nil;
[configURL release], configURL = nil;
[adNetworkConfigs release], adNetworkConfigs = nil;
[backgroundColor release], backgroundColor = nil;
[textColor release], textColor = nil;
[delegates release], delegates = nil;
[super dealloc];
}
#pragma mark parsing methods
- (BOOL)parseExtraConfig:(NSDictionary *)configDict error:(NSError **)error {
id bgColor = [configDict objectForKey:@"background_color_rgb"];
if (bgColor != nil && [bgColor isKindOfClass:[NSDictionary class]]) {
[backgroundColor release];
backgroundColor = [[UIColor alloc] initWithDict:(NSDictionary *)bgColor];
}
id txtColor = [configDict objectForKey:@"text_color_rgb"];
if (txtColor != nil && [txtColor isKindOfClass:[NSDictionary class]]) {
[textColor release];
textColor = [[UIColor alloc] initWithDict:txtColor];
}
id tempVal;
tempVal = [configDict objectForKey:@"refresh_interval"];
if (tempVal == nil)
tempVal = [configDict objectForKey:@"cycle_time"];
NSInteger tempInt;
if (tempVal && awIntVal(&tempInt, tempVal)) {
refreshInterval = (NSTimeInterval)tempInt;
if (refreshInterval >= 30000.0) {
// effectively forever, set to 0
refreshInterval = 0.0;
}
}
if (awIntVal(&tempInt, [configDict objectForKey:@"location_on"])) {
locationOn = (tempInt == 0)? NO : YES;
// check user preference. user preference of NO trumps all
BOOL bLocationServiceEnabled = NO;
if ([CLLocationManager respondsToSelector:
@selector(locationServicesEnabled)]) {
bLocationServiceEnabled = [CLLocationManager locationServicesEnabled];
}
else {
CLLocationManager* locMan = [[CLLocationManager alloc] init];
bLocationServiceEnabled = locMan.locationServicesEnabled;
[locMan release], locMan = nil;
}
if (locationOn == YES && bLocationServiceEnabled == NO) {
AWLogDebug(@"User disabled location services, set locationOn to NO");
locationOn = NO;
}
}
tempVal = [configDict objectForKey:@"transition"];
if (tempVal == nil)
tempVal = [configDict objectForKey:@"banner_animation_type"];
if (tempVal && awIntVal(&tempInt, tempVal)) {
switch (tempInt) {
case 0: bannerAnimationType = AWBannerAnimationTypeNone; break;
case 1: bannerAnimationType = AWBannerAnimationTypeFlipFromLeft; break;
case 2: bannerAnimationType = AWBannerAnimationTypeFlipFromRight; break;
case 3: bannerAnimationType = AWBannerAnimationTypeCurlUp; break;
case 4: bannerAnimationType = AWBannerAnimationTypeCurlDown; break;
case 5: bannerAnimationType = AWBannerAnimationTypeSlideFromLeft; break;
case 6: bannerAnimationType = AWBannerAnimationTypeSlideFromRight; break;
case 7: bannerAnimationType = AWBannerAnimationTypeFadeIn; break;
case 8: bannerAnimationType = AWBannerAnimationTypeRandom; break;
}
}
if (awIntVal(&tempInt, [configDict objectForKey:@"fullscreen_wait_interval"])) {
fullscreenWaitInterval = tempInt;
}
if (awIntVal(&tempInt, [configDict objectForKey:@"fullscreen_max_ads"])) {
fullscreenMaxAds = tempInt;
}
return YES;
}
- (BOOL)parseLegacyConfig:(NSArray *)configArray error:(NSError **)error {
NSMutableDictionary *adNetConfigDicts = [[NSMutableDictionary alloc] init];
for (int i = 0; i < [configArray count]; i++) {
id configObj = [configArray objectAtIndex:i];
if (![configObj isKindOfClass:[NSDictionary class]]) {
if (error != NULL)
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:@"Expected dictionary in config data"];
[adNetConfigDicts release];
return NO;
}
NSDictionary *configDict = (NSDictionary *)configObj;
switch (i) {
case 0:
// ration map
case 1:
// key map
case 2:
// priority map
for (id key in [configDict keyEnumerator]) {
// format: "<network name>_<value name>" e.g. "admob_ration"
NSString *strKey = (NSString *)key;
if ([strKey compare:@"empty_ration"] == NSOrderedSame) {
NSInteger empty_ration;
if (awIntVal(&empty_ration, [configDict objectForKey:key]) && empty_ration == 100) {
adsAreOff = YES;
[adNetConfigDicts release];
return YES;
}
}
adsAreOff = NO;
NSRange underScorePos = [strKey rangeOfString:@"_" options:NSBackwardsSearch];
if (underScorePos.location == NSNotFound) {
if (error != NULL)
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:[NSString stringWithFormat:
@"Expected underscore delimiter in key '%@'", strKey]];
[adNetConfigDicts release];
return NO;
}
NSString *networkName = [strKey substringToIndex:underScorePos.location];
NSString *valueName = [strKey substringFromIndex:(underScorePos.location+1)];
if ([networkName length] == 0) {
if (error != NULL)
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:[NSString stringWithFormat:
@"Empty ad network name in key '%@'", strKey]];
[adNetConfigDicts release];
return NO;
}
if ([valueName length] == 0) {
if (error != NULL)
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:[NSString stringWithFormat:
@"Empty value name in key '%@'", strKey]];
[adNetConfigDicts release];
return NO;
}
if ([networkName compare:@"dontcare"] == NSOrderedSame) {
continue;
}
NSMutableDictionary *adNetConfigDict = [adNetConfigDicts objectForKey:networkName];
if (adNetConfigDict == nil) {
adNetConfigDict = [[NSMutableDictionary alloc] init];
[adNetConfigDicts setObject:adNetConfigDict forKey:networkName];
[adNetConfigDict release];
adNetConfigDict = [adNetConfigDicts objectForKey:networkName];
}
NSString *properValueName;
if ([valueName compare:@"ration"] == NSOrderedSame) {
properValueName = AWAdNetworkConfigKeyWeight;
}
else if ([valueName compare:@"key"] == NSOrderedSame) {
properValueName = AWAdNetworkConfigKeyCred;
}
else if ([valueName compare:@"priority"] == NSOrderedSame) {
properValueName = AWAdNetworkConfigKeyPriority;
}
else {
properValueName = valueName;
}
[adNetConfigDict setObject:[configDict objectForKey:key]
forKey:properValueName];
}
break; // ad network config maps
case 3:
// general config map
if (![self parseExtraConfig:configDict error:error]) {
return NO;
}
break; // general config map
default:
AWLogWarn(@"Ignoring element at index %d in legacy config", i);
break;
} // switch (i)
} // loop configArray
// adwhirl_ special handling
NSMutableDictionary *adRolloConfig = [adNetConfigDicts objectForKey:@"adrollo"];
if (adRolloConfig != nil) {
AWLogDebug(@"Processing AdRollo config %@", adRolloConfig);
NSMutableArray *adWhirlNetworkConfigs = [[NSMutableArray alloc] init];;
for (NSString *netname in [adNetConfigDicts keyEnumerator]) {
if (![netname hasPrefix:@"adwhirl_"]) continue;
[adWhirlNetworkConfigs addObject:[adNetConfigDicts objectForKey:netname]];
}
if ([adWhirlNetworkConfigs count] > 0) {
// split the ration evenly, use same credentials
NSInteger ration = [[adRolloConfig objectForKey:AWAdNetworkConfigKeyWeight] integerValue];
ration = ration/[adWhirlNetworkConfigs count];
for (NSMutableDictionary *cd in adWhirlNetworkConfigs) {
[cd setObject:[NSNumber numberWithInteger:ration]
forKey:AWAdNetworkConfigKeyWeight];
[cd setObject:[adRolloConfig objectForKey:AWAdNetworkConfigKeyCred]
forKey:AWAdNetworkConfigKeyCred];
}
}
[adWhirlNetworkConfigs release];
}
NSInteger totalWeight = 0;
for (id networkName in [adNetConfigDicts keyEnumerator]) {
NSString *netname = (NSString *)networkName;
if ([netname compare:@"adrollo"] == NSOrderedSame) {
// skip adrollo, was used for "adwhirl_" networks
continue;
}
NSMutableDictionary *adNetConfigDict = [adNetConfigDicts objectForKey:netname];
// set network type for legacy
NSInteger networkType = 0;
if ([netname compare:@"admob"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeAdMob;
}
else if ([netname compare:@"jumptap"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeJumpTap;
}
else if ([netname compare:@"videoegg"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeVideoEgg;
}
else if ([netname compare:@"medialets"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeMedialets;
}
else if ([netname compare:@"liverail"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeLiveRail;
}
else if ([netname compare:@"millennial"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeMillennial;
}
else if ([netname compare:@"greystripe"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeGreyStripe;
}
else if ([netname compare:@"quattro"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeQuattro;
}
else if ([netname compare:@"custom"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeCustom;
}
else if ([netname compare:@"adwhirl_10"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeAdWhirl10;
}
else if ([netname compare:@"mobclix"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeMobClix;
}
else if ([netname compare:@"adwhirl_12"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeMdotM;
}
else if ([netname compare:@"adwhirl_13"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeAdWhirl13;
}
else if ([netname compare:@"google_adsense"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeGoogleAdSense;
}
else if ([netname compare:@"google_doubleclick"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeGoogleDoubleClick;
}
else if ([netname compare:@"generic"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeGeneric;
}
else if ([netname compare:@"inmobi"] == NSOrderedSame) {
networkType = AdWhirlAdNetworkTypeInMobi;
}
else {
AWLogWarn(@"Unrecognized ad network '%@' in legacy config, ignored", netname);
continue;
}
[adNetConfigDict setObject:netname forKey:AWAdNetworkConfigKeyName];
[adNetConfigDict setObject:[NSString stringWithFormat:@"%d", networkType]
forKey:AWAdNetworkConfigKeyNID];
[adNetConfigDict setObject:[NSNumber numberWithInteger:networkType]
forKey:AWAdNetworkConfigKeyType];
AdWhirlError *adNetConfigError = nil;
AdWhirlAdNetworkConfig *adNetConfig =
[[AdWhirlAdNetworkConfig alloc] initWithDictionary:adNetConfigDict
adNetworkRegistry:adNetworkRegistry
error:&adNetConfigError];
if (adNetConfig != nil) {
[adNetworkConfigs addObject:adNetConfig];
totalWeight += adNetConfig.trafficPercentage;
[adNetConfig release];
}
else {
AWLogWarn(@"Cannot create ad network config from %@: %@", adNetConfigDict,
adNetConfigError != nil? [adNetConfigError localizedDescription]:@"");
}
} // for each ad network name
if (totalWeight == 0) {
adsAreOff = YES;
}
[adNetConfigDicts release];
return YES;
}
- (BOOL)parseNewConfig:(NSDictionary *)configDict error:(NSError **)error {
id extra = [configDict objectForKey:@"extra"];
if (extra != nil && [extra isKindOfClass:[NSDictionary class]]) {
NSDictionary *extraDict = extra;
if (![self parseExtraConfig:extraDict error:error]) {
return NO;
}
}
else {
AWLogWarn(@"No extra info dict in ad network config");
}
id rations = [configDict objectForKey:@"rations"];
double totalWeight = 0.0;
if (rations != nil && [rations isKindOfClass:[NSArray class]]) {
if ([(NSArray *)rations count] == 0) {
adsAreOff = YES;
return YES;
}
adsAreOff = NO;
for (id c in (NSArray *)rations) {
if (![c isKindOfClass:[NSDictionary class]]) {
AWLogWarn(@"Element in rations array is not a dictionary %@ in ad network config",c);
continue;
}
AdWhirlError *adNetConfigError = nil;
AdWhirlAdNetworkConfig *adNetConfig =
[[AdWhirlAdNetworkConfig alloc] initWithDictionary:(NSDictionary *)c
adNetworkRegistry:adNetworkRegistry
error:&adNetConfigError];
if (adNetConfig != nil) {
[adNetworkConfigs addObject:adNetConfig];
totalWeight += adNetConfig.trafficPercentage;
[adNetConfig release];
}
else {
AWLogWarn(@"Cannot create ad network config from %@: %@", c,
adNetConfigError != nil? [adNetConfigError localizedDescription]:@"");
}
}
}
else {
AWLogError(@"No rations array in ad network config");
}
if (totalWeight == 0.0) {
adsAreOff = YES;
}
return YES;
}
- (BOOL)parseConfig:(NSData *)data error:(NSError **)error {
if (hasConfig) {
if (error != NULL)
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:@"Already has config, will not parse"];
return NO;
}
NSError *jsonError = nil;
id parsed = [[CJSONDeserializer deserializer] deserialize:data error:&jsonError];
if (parsed == nil) {
if (error != NULL)
*error = [AdWhirlError errorWithCode:AdWhirlConfigParseError
description:@"Error parsing config JSON from server"
underlyingError:jsonError];
return NO;
}
if ([parsed isKindOfClass:[NSArray class]]) {
// pre-open-source AdWhirl/AdRollo config
legacy = YES;
if (![self parseLegacyConfig:(NSArray *)parsed error:error]) {
return NO;
}
}
else if ([parsed isKindOfClass:[NSDictionary class]]) {
// open-source AdWhirl config
if (![self parseNewConfig:(NSDictionary *)parsed error:error]) {
return NO;
}
}
else {
if (error != NULL)
*error = [AdWhirlError errorWithCode:AdWhirlConfigDataError
description:@"Expected top-level dictionary in config data"];
return NO;
}
// parse success
hasConfig = YES;
// notify delegates of success
for (NSValue *wrapped in delegates) {
id<AdWhirlConfigDelegate> delegate = [wrapped nonretainedObjectValue];
if ([delegate respondsToSelector:@selector(adWhirlConfigDidReceiveConfig:)]) {
[delegate adWhirlConfigDidReceiveConfig:self];
}
}
return YES;
}
@end
@@ -0,0 +1,67 @@
/*
AdWhirlConfigStore.h
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
#import "AdWhirlConfigStore.h"
#import "AdWhirlConfig.h"
#import "AWNetworkReachabilityDelegate.h"
@class AWNetworkReachabilityWrapper;
// Singleton class to store AdWhirl configs, keyed by appKey. Fetched config
// is cached unless it is force-fetched using fetchConfig. Checks network
// reachability using AWNetworkReachabilityWrapper before making connections to
// fetch configs, so that that means it will wait forever until the config host
// is reachable.
@interface AdWhirlConfigStore : NSObject <AWNetworkReachabilityDelegate> {
NSMutableDictionary *configs_;
AdWhirlConfig *fetchingConfig_;
AWNetworkReachabilityWrapper *reachability_;
NSURLConnection *connection_;
NSMutableData *receivedData_;
}
// Returns the singleton AdWhirlConfigStore object.
+ (AdWhirlConfigStore *)sharedStore;
// Deletes all existing configs.
+ (void)resetStore;
// Returns config for appKey. If config does not exist for appKey, goes and
// fetches the config from the server, the URL of which is taken from
// [delegate adWhirlConfigURL].
// Returns nil if appKey is nil or empty, another fetch is in progress, or
// error setting up reachability check.
- (AdWhirlConfig *)getConfig:(NSString *)appKey
delegate:(id<AdWhirlConfigDelegate>)delegate;
// Fetches (or re-fetch) the config for the given appKey. Always go to the
// network. Call this to get a new version of the config from the server.
// Returns nil if appKey is nil or empty, another fetch is in progress, or
// error setting up reachability check.
- (AdWhirlConfig *)fetchConfig:(NSString *)appKey
delegate:(id <AdWhirlConfigDelegate>)delegate;
// For testing -- set mocks here.
@property (nonatomic,retain) AWNetworkReachabilityWrapper *reachability;
@property (nonatomic,retain) NSURLConnection *connection;
@end
@@ -0,0 +1,291 @@
/*
AdWhirlConfigStore.m
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlConfigStore.h"
#import "AdWhirlLog.h"
#import "AWNetworkReachabilityWrapper.h"
#import "AdWhirlError.h"
static AdWhirlConfigStore *gStore = nil;
@interface AdWhirlConfigStore ()
- (BOOL)checkReachability;
- (void)startFetchingAssumingReachable;
- (void)failedFetchingWithError:(AdWhirlError *)error;
- (void)finishedFetching;
@end
@implementation AdWhirlConfigStore
@synthesize reachability = reachability_;
@synthesize connection = connection_;
+ (AdWhirlConfigStore *)sharedStore {
if (gStore == nil) {
gStore = [[AdWhirlConfigStore alloc] init];
}
return gStore;
}
+ (void)resetStore {
if (gStore != nil) {
[gStore release], gStore = nil;
[self sharedStore];
}
}
- (id)init {
self = [super init];
if (self != nil) {
configs_ = [[NSMutableDictionary alloc] init];
}
return self;
}
- (AdWhirlConfig *)getConfig:(NSString *)appKey
delegate:(id<AdWhirlConfigDelegate>)delegate {
AdWhirlConfig *config = [configs_ objectForKey:appKey];
if (config != nil) {
if (config.hasConfig) {
if ([delegate
respondsToSelector:@selector(adWhirlConfigDidReceiveConfig:)]) {
// Don't call directly, instead schedule it in the runloop. Delegate
// may expect the message to be delivered out-of-band
[(NSObject *)delegate
performSelectorOnMainThread:@selector(adWhirlConfigDidReceiveConfig:)
withObject:config
waitUntilDone:NO];
}
return config;
}
// If there's already a config fetching, and another call to this function
// add a delegate to the config
[config addDelegate:delegate];
return config;
}
// No config, create one, and start fetching it
return [self fetchConfig:appKey delegate:delegate];
}
- (AdWhirlConfig *)fetchConfig:(NSString *)appKey
delegate:(id <AdWhirlConfigDelegate>)delegate {
AdWhirlConfig *config = [[AdWhirlConfig alloc] initWithAppKey:appKey
delegate:delegate];
if (fetchingConfig_ != nil) {
AWLogWarn(@"Another fetch is in progress, wait until finished.");
[config release];
return nil;
}
fetchingConfig_ = config;
if (![self checkReachability]) {
[config release];
return nil;
}
[configs_ setObject:config forKey:appKey];
[config release];
return config;
}
- (void)dealloc {
if (reachability_ != nil) {
reachability_.delegate = nil;
[reachability_ release];
}
[connection_ release];
[receivedData_ release];
[configs_ release];
[super dealloc];
}
#pragma mark private helper methods
// Check reachability first
- (BOOL)checkReachability {
AWLogDebug(@"Checking if config is reachable at %@",
fetchingConfig_.configURL);
// Normally reachability_ should be nil so a new one will be created.
// In a testing environment, it may already have been assigned with a mock.
// In any case, reachability_ will be released when the config URL is
// reachable, in -reachabilityBecameReachable.
if (reachability_ == nil) {
reachability_ = [AWNetworkReachabilityWrapper
reachabilityWithHostname:[fetchingConfig_.configURL host]
callbackDelegate:self];
[reachability_ retain];
}
if (reachability_ == nil) {
[fetchingConfig_ notifyDelegatesOfFailure:
[AdWhirlError errorWithCode:AdWhirlConfigConnectionError
description:
@"Error setting up reachability check to config server"]];
return NO;
}
if (![reachability_ scheduleInCurrentRunLoop]) {
[fetchingConfig_ notifyDelegatesOfFailure:
[AdWhirlError errorWithCode:AdWhirlConfigConnectionError
description:
@"Error scheduling reachability check to config server"]];
[reachability_ release], reachability_ = nil;
return NO;
}
return YES;
}
// Make connection
- (void)startFetchingAssumingReachable {
// go fetch config
NSURLRequest *configRequest
= [NSURLRequest requestWithURL:fetchingConfig_.configURL];
// Normally connection_ should be nil so a new one will be created.
// In a testing environment, it may alreay have been assigned with a mock.
// In any case, connection_ will be release when connection failed or
// finished.
if (connection_ == nil) {
connection_ = [[NSURLConnection alloc] initWithRequest:configRequest
delegate:self];
}
// Error checking
if (connection_ == nil) {
[self failedFetchingWithError:
[AdWhirlError errorWithCode:AdWhirlConfigConnectionError
description:
@"Error creating connection to config server"]];
return;
}
receivedData_ = [[NSMutableData alloc] init];
}
// Clean up after fetching failed
- (void)failedFetchingWithError:(AdWhirlError *)error {
// notify
[fetchingConfig_ notifyDelegatesOfFailure:error];
// remove the failed config from the cache
[configs_ removeObjectForKey:fetchingConfig_.appKey];
// the config is only retained by the dict,now released
[self finishedFetching];
}
// Clean up after fetching, success or failed
- (void)finishedFetching {
[connection_ release], connection_ = nil;
[receivedData_ release], receivedData_ = nil;
fetchingConfig_ = nil;
}
#pragma mark reachability methods
- (void)reachabilityNotReachable:(AWNetworkReachabilityWrapper *)reach {
if (reach != reachability_) {
AWLogWarn(@"Unrecognized reachability object called not reachable %s:%d",
__FILE__, __LINE__);
return;
}
AWLogDebug(@"Config host %@ not (yet) reachable, check back later",
reach.hostname);
[reachability_ release], reachability_ = nil;
[self performSelector:@selector(checkReachability)
withObject:nil
afterDelay:10.0];
}
- (void)reachabilityBecameReachable:(AWNetworkReachabilityWrapper *)reach {
if (reach != reachability_) {
AWLogWarn(@"Unrecognized reachability object called reachable %s:%d",
__FILE__, __LINE__);
return;
}
// done with the reachability
[reachability_ release], reachability_ = nil;
[self startFetchingAssumingReachable];
}
#pragma mark NSURLConnection delegate methods.
- (void)connection:(NSURLConnection *)conn
didReceiveResponse:(NSURLResponse *)response {
if (conn != connection_) {
AWLogError(@"Unrecognized connection object %s:%d", __FILE__, __LINE__);
return;
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *http = (NSHTTPURLResponse*)response;
const int status = [http statusCode];
if (status < 200 || status >= 300) {
AWLogWarn(@"AdWhirlConfig: HTTP %d, cancelling %@", status, [http URL]);
[connection_ cancel];
[self failedFetchingWithError:
[AdWhirlError errorWithCode:AdWhirlConfigStatusError
description:@"Config server did not return status 200"]];
return;
}
}
[receivedData_ setLength:0];
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error {
if (conn != connection_) {
AWLogError(@"Unrecognized connection object %s:%d", __FILE__, __LINE__);
return;
}
[self failedFetchingWithError:
[AdWhirlError errorWithCode:AdWhirlConfigConnectionError
description:@"Error connecting to config server"
underlyingError:error]];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn {
if (conn != connection_) {
AWLogError(@"Unrecognized connection object %s:%d", __FILE__, __LINE__);
return;
}
[fetchingConfig_ parseConfig:receivedData_ error:nil];
[self finishedFetching];
}
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data {
if (conn != connection_) {
AWLogError(@"Unrecognized connection object %s:%d", __FILE__, __LINE__);
return;
}
[receivedData_ appendData:data];
}
@end
@@ -0,0 +1,101 @@
/*
AdWhirlCustomAdView.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef enum {
AWCustomAdTypeMIN = 0,
AWCustomAdTypeBanner = 1,
AWCustomAdTypeText = 2,
AWCustomAdTypeAutoLaunchFallBackBanner = 3,
AWCustomAdTypeAutoLaunchFallBackText = 4,
AWCustomAdTypeSearchBar = 5,
AWCustomAdTypeMAX = 6
} AWCustomAdType;
typedef enum {
AWCustomAdLaunchTypeMIN = 0,
AWCustomAdLaunchTypeSafari = 1,
AWCustomAdLaunchTypeCanvas = 2,
AWCustomAdLaunchTypeSafariRedirectFollowThrough = 3,
AWCustomAdLaunchTypeMAX = 4
} AWCustomAdLaunchType;
typedef enum {
AWCustomAdWebViewAnimTypeMIN = -1,
AWCustomAdWebViewAnimTypeNone = 0,
AWCustomAdWebViewAnimTypeFlipFromLeft = 1,
AWCustomAdWebViewAnimTypeFlipFromRight = 2,
AWCustomAdWebViewAnimTypeCurlUp = 3,
AWCustomAdWebViewAnimTypeCurlDown = 4,
AWCustomAdWebViewAnimTypeSlideFromLeft = 5,
AWCustomAdWebViewAnimTypeSlideFromRight = 6,
AWCustomAdWebViewAnimTypeFadeIn = 7,
AWCustomAdWebViewAnimTypeModal = 8,
AWCustomAdWebViewAnimTypeRandom = 9,
AWCustomAdWebViewAnimTypeMAX = 10
} AWCustomAdWebViewAnimType;
@class AdWhirlCustomAdView;
@protocol AdWhirlCustomAdViewDelegate<NSObject>
- (void)adTapped:(AdWhirlCustomAdView *)adView;
@end
@interface AdWhirlCustomAdView : UIButton
{
id<AdWhirlCustomAdViewDelegate> delegate;
UIImage *image;
UILabel *textLabel;
NSURL *redirectURL;
NSURL *clickMetricsURL;
AWCustomAdType adType;
AWCustomAdLaunchType launchType;
AWCustomAdWebViewAnimType animType;
UIColor *backgroundColor;
UIColor *textColor;
}
- (id)initWithDelegate:(id<AdWhirlCustomAdViewDelegate>)delegate
text:(NSString *)text
redirectURL:(NSURL *)redirectURL
clickMetricsURL:(NSURL *)clickMetricsURL
adType:(AWCustomAdType)adType
launchType:(AWCustomAdLaunchType)launchType
animType:(AWCustomAdWebViewAnimType)animType
backgroundColor:(UIColor *)bgColor
textColor:(UIColor *)fgColor;
@property (nonatomic,assign) id<AdWhirlCustomAdViewDelegate> delegate;
@property (nonatomic,retain) UIImage *image;
@property (nonatomic,readonly) UILabel *textLabel;
@property (nonatomic,readonly) NSURL *redirectURL;
@property (nonatomic,readonly) NSURL *clickMetricsURL;
@property (nonatomic,readonly) AWCustomAdType adType;
@property (nonatomic,readonly) AWCustomAdLaunchType launchType;
@property (nonatomic,readonly) AWCustomAdWebViewAnimType animType;
@property (nonatomic,readonly) UIColor *backgroundColor;
@property (nonatomic,readonly) UIColor *textColor;
@end
@@ -0,0 +1,168 @@
/*
AdWhirlCustomAdView.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlCustomAdView.h"
#import "AdWhirlView.h"
#import "AdWhirlLog.h"
@implementation AdWhirlCustomAdView
@synthesize delegate;
@synthesize image;
@synthesize textLabel;
@synthesize redirectURL;
@synthesize clickMetricsURL;
@synthesize adType;
@synthesize launchType;
@synthesize animType;
@synthesize backgroundColor;
@synthesize textColor;
- (id)initWithDelegate:(id<AdWhirlCustomAdViewDelegate>)d
text:(NSString *)txt
redirectURL:(NSURL *)rURL
clickMetricsURL:(NSURL *)cURL
adType:(AWCustomAdType)aType
launchType:(AWCustomAdLaunchType)launch
animType:(AWCustomAdWebViewAnimType)anim
backgroundColor:(UIColor *)bgColor
textColor:(UIColor *)fgColor {
self = [super initWithFrame:kAdWhirlViewDefaultFrame];
if (self != nil) {
delegate = d;
redirectURL = [rURL retain];
clickMetricsURL = [cURL retain];
adType = aType;
launchType = launch;
animType = anim;
backgroundColor = [bgColor retain];
textColor = [fgColor retain];
if (adType == AWCustomAdTypeText) {
textLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 270, CGRectGetHeight(self.bounds))];
textLabel.text = txt;
textLabel.textColor = fgColor;
textLabel.numberOfLines = 3;
textLabel.backgroundColor = [UIColor clearColor];
textLabel.font = [UIFont fontWithName:@"TrebuchetMS-Bold" size:13.0];
[self addSubview:textLabel];
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = self.bounds;
button.showsTouchWhenHighlighted = YES;
[button addTarget:self action:@selector(buttonTapUp:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
}
return self;
}
#define kNumBgColors 3
#define kImageLeft 4
#define kCornerRadius 7.0
#define kImageDim 39 // assume square, so this is length of each side
#define kChamferLight [UIColor colorWithWhite:0.9 alpha:1].CGColor
#define kChamferDark [UIColor colorWithWhite:0.4 alpha:1].CGColor
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
if (adType == AWCustomAdTypeText) {
// draw background
CGFloat locations[kNumBgColors] = {0.0, 0.7, 1.0};
CGColorRef colorArray[kNumBgColors] =
{[backgroundColor colorWithAlphaComponent:0.6].CGColor,
backgroundColor.CGColor,
backgroundColor.CGColor};
CFArrayRef colors = CFArrayCreate(kCFAllocatorDefault,
(const void **)colorArray,
kNumBgColors,
&kCFTypeArrayCallBacks);
CGGradientRef gradient = CGGradientCreateWithColors(NULL, colors, locations);
CFRelease(colors);
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextFillRect(ctx, CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)));
CGPoint midY = CGPointMake(0.0, CGRectGetHeight(self.bounds)/2);
CGPoint lowY = CGPointMake(0.0, CGRectGetHeight(self.bounds));
CGContextDrawLinearGradient(ctx, gradient, CGPointZero, midY, 0);
CGContextDrawLinearGradient(ctx, gradient, lowY, midY, 0);
CGGradientRelease(gradient);
// draw image and chamfer
CGFloat imageTop = (CGRectGetHeight(self.bounds) - kImageDim)/2.0;
CGPoint tl = CGPointMake(kImageLeft+kCornerRadius, imageTop+kCornerRadius);
CGPoint tr = CGPointMake(kImageLeft+kImageDim-kCornerRadius, imageTop+kCornerRadius);
CGPoint br = CGPointMake(kImageLeft+kImageDim-kCornerRadius, imageTop+kImageDim-kCornerRadius);
CGPoint bl = CGPointMake(kImageLeft+kCornerRadius, imageTop+kImageDim-kCornerRadius);
CGContextSaveGState(ctx);
CGContextMoveToPoint(ctx, kImageLeft, imageTop+kCornerRadius);
CGContextAddArc(ctx, tl.x, tl.y, kCornerRadius, M_PI, 3*M_PI/2, 0);
CGContextAddArc(ctx, tr.x, tr.y, kCornerRadius, 3*M_PI/2, 0, 0);
CGContextAddArc(ctx, br.x, br.y, kCornerRadius, 0, M_PI/2, 0);
CGContextAddArc(ctx, bl.x, bl.y, kCornerRadius, M_PI/2, M_PI, 0);
CGContextClosePath(ctx);
CGContextClip(ctx);
[image drawAtPoint:CGPointMake(kImageLeft, imageTop)];
CGContextSetLineWidth(ctx, 0.5);
CGContextMoveToPoint(ctx, kImageLeft, imageTop+kImageDim-kCornerRadius);
CGContextSetStrokeColorWithColor(ctx, kChamferDark);
CGContextAddArc(ctx, tl.x, tl.y, kCornerRadius, M_PI, 5*M_PI/4, 0);
CGContextStrokePath(ctx);
CGContextSetStrokeColorWithColor(ctx, kChamferLight);
CGContextAddArc(ctx, tl.x, tl.y, kCornerRadius, 5*M_PI/4, 3*M_PI/2, 0);
CGContextAddArc(ctx, tr.x, tr.y, kCornerRadius, 3*M_PI/2, 0, 0);
CGContextAddArc(ctx, br.x, br.y, kCornerRadius, 0, M_PI/4, 0);
CGContextStrokePath(ctx);
CGContextSetStrokeColorWithColor(ctx, kChamferDark);
CGContextAddArc(ctx, br.x, br.y, kCornerRadius, M_PI/4, M_PI/2, 0);
CGContextAddArc(ctx, bl.x, bl.y, kCornerRadius, M_PI/2, M_PI, 0);
CGContextStrokePath(ctx);
CGContextRestoreGState(ctx);
} // text ad
else if (adType == AWCustomAdTypeBanner) {
// draw image, place image in center of frame
[image drawAtPoint:CGPointMake((self.frame.size.width-image.size.width)/2,
(self.frame.size.height-image.size.height)/2)];
} // banner ad
}
- (void)dealloc {
[image release], image = nil;
[textLabel release], textLabel = nil;
[redirectURL release], redirectURL = nil;
[clickMetricsURL release], clickMetricsURL = nil;
[backgroundColor release], backgroundColor = nil;
[textColor release], textColor = nil;
[super dealloc];
}
#pragma mark UIButton control events
- (void)buttonTapUp:(id)sender {
if (delegate != nil) {
[delegate adTapped:self];
}
}
@end
@@ -0,0 +1,55 @@
/*
AdWhirlError.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
#define AdWhirlErrorDomain @"com.adwhirl.sdk.ErrorDomain"
enum {
AdWhirlConfigConnectionError = 10, /* Cannot connect to config server */
AdWhirlConfigStatusError = 11, /* config server did not return 200 */
AdWhirlConfigParseError = 20, /* Error parsing config from server */
AdWhirlConfigDataError = 30, /* Invalid config format from server */
AdWhirlCustomAdConnectionError = 40, /* Cannot connect to custom ad server */
AdWhirlCustomAdParseError = 50, /* Error parsing custom ad from server */
AdWhirlCustomAdDataError = 60, /* Invalid custom ad data from server */
AdWhirlCustomAdImageError = 70, /* Cannot create image from data */
AdWhirlAdRequestIgnoredError = 80, /* ignoreNewAdRequests flag is set */
AdWhirlAdRequestInProgressError = 90, /* ad request in progress */
AdWhirlAdRequestNoConfigError = 100, /* no configurations for ad request */
AdWhirlAdRequestTooSoonError = 110, /* requesting ad too soon */
AdWhirlAdRequestNoMoreAdNetworks = 120, /* no more ad networks for rollover */
AdWhirlAdRequestNoNetworkError = 130, /* no network connection */
AdWhirlAdRequestModalActiveError = 140 /* modal view active */
};
@interface AdWhirlError : NSError {
}
+ (AdWhirlError *)errorWithCode:(NSInteger)code userInfo:(NSDictionary *)dict;
+ (AdWhirlError *)errorWithCode:(NSInteger)code description:(NSString *)desc;
+ (AdWhirlError *)errorWithCode:(NSInteger)code description:(NSString *)desc underlyingError:(NSError *)uError;
- (id)initWithCode:(NSInteger)code userInfo:(NSDictionary *)dict;
- (id)initWithCode:(NSInteger)code description:(NSString *)desc;
- (id)initWithCode:(NSInteger)code description:(NSString *)desc underlyingError:(NSError *)uError;
@end
@@ -0,0 +1,56 @@
/*
AdWhirlError.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlError.h"
@implementation AdWhirlError
+ (AdWhirlError *)errorWithCode:(NSInteger)code userInfo:(NSDictionary *)dict {
return [[[AdWhirlError alloc] initWithCode:code userInfo:dict] autorelease];
}
+ (AdWhirlError *)errorWithCode:(NSInteger)code description:(NSString *)desc {
return [[[AdWhirlError alloc] initWithCode:code description:desc] autorelease];
}
+ (AdWhirlError *)errorWithCode:(NSInteger)code description:(NSString *)desc underlyingError:(NSError *)uError {
return [[[AdWhirlError alloc] initWithCode:code description:desc underlyingError:uError] autorelease];
}
- (id)initWithCode:(NSInteger)code userInfo:(NSDictionary *)dict {
return [super initWithDomain:AdWhirlErrorDomain code:code userInfo:dict];
}
- (id)initWithCode:(NSInteger)code description:(NSString *)desc {
NSDictionary *eInfo = [NSDictionary dictionaryWithObjectsAndKeys:
desc, NSLocalizedDescriptionKey,
nil];
return [super initWithDomain:AdWhirlErrorDomain code:code userInfo:eInfo];
}
- (id)initWithCode:(NSInteger)code description:(NSString *)desc underlyingError:(NSError *)uError {
NSDictionary *eInfo = [NSDictionary dictionaryWithObjectsAndKeys:
desc, NSLocalizedDescriptionKey,
uError, NSUnderlyingErrorKey,
nil];
return [super initWithDomain:AdWhirlErrorDomain code:code userInfo:eInfo];
}
@end
@@ -0,0 +1,61 @@
/*
AdWhirlLog.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
typedef enum {
AWLogLevelNone = 0,
AWLogLevelCrit = 10,
AWLogLevelError = 20,
AWLogLevelWarn = 30,
AWLogLevelInfo = 40,
AWLogLevelDebug = 50
} AWLogLevel;
void AWLogSetLogLevel(AWLogLevel level);
// The actual function name has an underscore prefix, just so we can
// hijack AWLog* with other functions for testing, by defining
// preprocessor macros
void _AWLogCrit(NSString *format, ...);
void _AWLogError(NSString *format, ...);
void _AWLogWarn(NSString *format, ...);
void _AWLogInfo(NSString *format, ...);
void _AWLogDebug(NSString *format, ...);
#ifndef AWLogCrit
#define AWLogCrit(...) _AWLogCrit(__VA_ARGS__)
#endif
#ifndef AWLogError
#define AWLogError(...) _AWLogError(__VA_ARGS__)
#endif
#ifndef AWLogWarn
#define AWLogWarn(...) _AWLogWarn(__VA_ARGS__)
#endif
#ifndef AWLogInfo
#define AWLogInfo(...) _AWLogInfo(__VA_ARGS__)
#endif
#ifndef AWLogDebug
#define AWLogDebug(...) _AWLogDebug(__VA_ARGS__)
#endif
@@ -0,0 +1,67 @@
/*
AdWhirlLog.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlLog.h"
static AWLogLevel g_AWLogLevel = AWLogLevelInfo;
void AWLogSetLogLevel(AWLogLevel level) {
g_AWLogLevel = level;
}
void _AWLogCrit(NSString *format, ...) {
if (g_AWLogLevel < AWLogLevelCrit) return;
va_list ap;
va_start(ap, format);
NSLogv(format, ap);
va_end(ap);
}
void _AWLogError(NSString *format, ...) {
if (g_AWLogLevel < AWLogLevelError) return;
va_list ap;
va_start(ap, format);
NSLogv(format, ap);
va_end(ap);
}
void _AWLogWarn(NSString *format, ...) {
if (g_AWLogLevel < AWLogLevelWarn) return;
va_list ap;
va_start(ap, format);
NSLogv(format, ap);
va_end(ap);
}
void _AWLogInfo(NSString *format, ...) {
if (g_AWLogLevel < AWLogLevelInfo) return;
va_list ap;
va_start(ap, format);
NSLogv(format, ap);
va_end(ap);
}
void _AWLogDebug(NSString *format, ...) {
if (g_AWLogLevel < AWLogLevelDebug) return;
va_list ap;
va_start(ap, format);
NSLogv(format, ap);
va_end(ap);
}
@@ -0,0 +1,60 @@
/*
AdWhirlView+.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlAdNetworkAdapter.h"
@class AdWhirlConfigStore;
@interface AdWhirlView ()
// Only initializes default values for member variables
- (id)initWithDelegate:(id<AdWhirlDelegate>)delegate;
// Kicks off getting config from AdWhirlConfigStore
- (void)startGetConfig;
- (void)buildPrioritizedAdNetCfgsAndMakeRequest;
- (AdWhirlAdNetworkConfig *)nextNetworkCfgByPercent;
- (AdWhirlAdNetworkConfig *)nextNetworkCfgByPriority;
- (void)makeAdRequest:(BOOL)isFirstRequest;
- (void)reportExImpression:(NSString *)nid netType:(AdWhirlAdNetworkType)type;
- (void)reportExClick:(NSString *)nid netType:(AdWhirlAdNetworkType)type;
- (BOOL)canRefresh;
- (void)resignActive:(NSNotification *)notification;
- (void)becomeActive:(NSNotification *)notification;
- (void)notifyDelegateOfErrorWithCode:(NSInteger)errorCode
description:(NSString *)desc;
- (void)notifyDelegateOfError:(NSError *)error;
@property (retain) AdWhirlConfig *config;
@property (retain) NSMutableArray *prioritizedAdNetCfgs;
@property (nonatomic,retain) AdWhirlAdNetworkAdapter *currAdapter;
@property (nonatomic,retain) AdWhirlAdNetworkAdapter *lastAdapter;
@property (nonatomic,retain) NSDate *lastRequestTime;
@property (nonatomic,retain) NSTimer *refreshTimer;
@property (nonatomic) BOOL showingModalView;
@property (nonatomic,assign) AdWhirlConfigStore *configStore;
@property (nonatomic,retain) AWNetworkReachabilityWrapper *rollOverReachability;
@property (nonatomic,retain) NSArray *testDarts;
@end
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,764 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">784</int>
<string key="IBDocument.SystemVersion">10D573</string>
<string key="IBDocument.InterfaceBuilderVersion">762</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">460.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">87</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="1"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBProxyObject" id="711762367">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="191373211">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBUIWebView" id="332242366">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">274</int>
<string key="NSFrameSize">{320, 436}</string>
<reference key="NSSuperview" ref="191373211"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace" id="139087982">
<int key="NSID">2</int>
</object>
</object>
<bool key="IBUIClipsSubviews">YES</bool>
<bool key="IBUIMultipleTouchEnabled">YES</bool>
<int key="IBUITag">2000</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBUIScalesPageToFit">YES</bool>
<int key="IBUIDataDetectorTypes">1</int>
<bool key="IBUIDetectsPhoneNumbers">YES</bool>
</object>
<object class="IBUIToolbar" id="498818201">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">266</int>
<string key="NSFrame">{{0, 436}, {320, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
<int key="IBUITag">1000</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableArray" key="IBUIItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBUIBarButtonItem" id="661950208">
<int key="IBUITag">1001</int>
<bool key="IBUIEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
</object>
<object class="IBUIBarButtonItem" id="202270411">
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">5</int>
</object>
<object class="IBUIBarButtonItem" id="624932652">
<int key="IBUITag">1002</int>
<bool key="IBUIEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">17</int>
</object>
<object class="IBUIBarButtonItem" id="694191601">
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">5</int>
</object>
<object class="IBUIBarButtonItem" id="507199361">
<int key="IBUITag">1003</int>
<bool key="IBUIEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">13</int>
</object>
<object class="IBUIBarButtonItem" id="1058448904">
<int key="IBUITag">1004</int>
<bool key="IBUIEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">14</int>
</object>
<object class="IBUIBarButtonItem" id="312829093">
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">5</int>
</object>
<object class="IBUIBarButtonItem" id="944463797">
<int key="IBUITag">1005</int>
<bool key="IBUIEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">9</int>
</object>
<object class="IBUIBarButtonItem" id="629368778">
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">5</int>
</object>
<object class="IBUIBarButtonItem" id="72154307">
<int key="IBUITag">1006</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<int key="IBUIStyle">1</int>
<reference key="IBUIToolbar" ref="498818201"/>
<int key="IBUISystemItemIdentifier">0</int>
</object>
</object>
<object class="NSColor" key="IBUITintColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
<reference key="NSCustomColorSpace" ref="139087982"/>
</object>
</object>
</object>
<string key="NSFrameSize">{320, 480}</string>
<reference key="NSSuperview"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
<reference key="NSCustomColorSpace" ref="139087982"/>
</object>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</object>
<object class="IBObjectContainer" key="IBDocument.Objects">
<object class="NSMutableArray" key="connectionRecords">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="191373211"/>
</object>
<int key="connectionID">10</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="332242366"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">13</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">back:</string>
<reference key="source" ref="661950208"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">41</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">forward:</string>
<reference key="source" ref="624932652"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">42</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">reload:</string>
<reference key="source" ref="507199361"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">43</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">stop:</string>
<reference key="source" ref="1058448904"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">44</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">linkOut:</string>
<reference key="source" ref="944463797"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">45</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">close:</string>
<reference key="source" ref="72154307"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">46</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">backButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="661950208"/>
</object>
<int key="connectionID">64</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">closeButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="72154307"/>
</object>
<int key="connectionID">65</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">forwardButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="624932652"/>
</object>
<int key="connectionID">66</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">linkOutButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="944463797"/>
</object>
<int key="connectionID">67</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">reloadButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="507199361"/>
</object>
<int key="connectionID">68</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">stopButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="1058448904"/>
</object>
<int key="connectionID">69</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">webView</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="332242366"/>
</object>
<int key="connectionID">70</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">toolBar</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="498818201"/>
</object>
<int key="connectionID">71</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord">
<int key="objectID">0</int>
<reference key="object" ref="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="191373211"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="498818201"/>
<reference ref="332242366"/>
</object>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="372490531"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="711762367"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">3</int>
<reference key="object" ref="332242366"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">4</int>
<reference key="object" ref="498818201"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="661950208"/>
<reference ref="624932652"/>
<reference ref="312829093"/>
<reference ref="944463797"/>
<reference ref="694191601"/>
<reference ref="202270411"/>
<reference ref="1058448904"/>
<reference ref="507199361"/>
<reference ref="629368778"/>
<reference ref="72154307"/>
</object>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="661950208"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="624932652"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">7</int>
<reference key="object" ref="507199361"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">8</int>
<reference key="object" ref="312829093"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">9</int>
<reference key="object" ref="944463797"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">25</int>
<reference key="object" ref="694191601"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">26</int>
<reference key="object" ref="202270411"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">31</int>
<reference key="object" ref="1058448904"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">39</int>
<reference key="object" ref="629368778"/>
<reference key="parent" ref="498818201"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">40</int>
<reference key="object" ref="72154307"/>
<reference key="parent" ref="498818201"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.CustomClassName</string>
<string>-2.CustomClassName</string>
<string>1.IBEditorWindowLastContentRect</string>
<string>1.IBPluginDependency</string>
<string>25.IBPluginDependency</string>
<string>26.IBPluginDependency</string>
<string>3.IBPluginDependency</string>
<string>31.IBPluginDependency</string>
<string>39.IBPluginDependency</string>
<string>4.IBPluginDependency</string>
<string>40.IBPluginDependency</string>
<string>5.CustomClassName</string>
<string>5.IBPluginDependency</string>
<string>6.IBPluginDependency</string>
<string>7.IBPluginDependency</string>
<string>8.IBPluginDependency</string>
<string>9.IBPluginDependency</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>AdWhirlWebBrowserController</string>
<string>UIResponder</string>
<string>{{577, 64}, {320, 480}}</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>AdWhirlBackButton</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object>
</object>
<object class="NSMutableDictionary" key="unlocalizedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="0"/>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<nil key="activeLocalization"/>
<object class="NSMutableDictionary" key="localizations">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="0"/>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">71</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">AdWhirlBackButton</string>
<string key="superclassName">UIBarButtonItem</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="40087982">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../AdWhirl/internal/AdWhirlWebBrowserController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">AdWhirlWebBrowserController</string>
<string key="superclassName">UIViewController</string>
<object class="NSMutableDictionary" key="actions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>back:</string>
<string>close:</string>
<string>forward:</string>
<string>linkOut:</string>
<string>reload:</string>
<string>stop:</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="outlets">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>backButton</string>
<string>closeButton</string>
<string>delegate</string>
<string>forwardButton</string>
<string>linkOutButton</string>
<string>reloadButton</string>
<string>stopButton</string>
<string>toolBar</string>
<string>webView</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>UIBarButtonItem</string>
<string>UIBarButtonItem</string>
<string>id</string>
<string>UIBarButtonItem</string>
<string>UIBarButtonItem</string>
<string>UIBarButtonItem</string>
<string>UIBarButtonItem</string>
<string>UIToolbar</string>
<string>UIWebView</string>
</object>
</object>
<reference key="sourceIdentifier" ref="40087982"/>
</object>
</object>
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSError.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="808166449">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIBarButtonItem</string>
<string key="superclassName">UIBarItem</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIBarButtonItem.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIBarItem</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIBarItem.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIResponder</string>
<string key="superclassName">NSObject</string>
<reference key="sourceIdentifier" ref="808166449"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">UISearchBar</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UISearchDisplayController</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIToolbar</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIToolbar.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIView</string>
<string key="superclassName">UIResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<string key="superclassName">UIResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIWebView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIWebView.h</string>
</object>
</object>
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<integer value="784" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<integer value="768" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
<integer value="3000" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../AdWhirlSDK2_Sample.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">87</string>
</data>
</archive>
@@ -0,0 +1,75 @@
/*
AdWhirlWebBrowserController.h
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "AdWhirlCustomAdView.h"
@class AdWhirlWebBrowserController;
@protocol AdWhirlWebBrowserControllerDelegate<NSObject>
- (void)webBrowserClosed:(AdWhirlWebBrowserController *)controller;
@end
@interface AdWhirlWebBrowserController : UIViewController <UIWebViewDelegate> {
id<AdWhirlWebBrowserControllerDelegate> delegate;
UIViewController *viewControllerForPresenting;
NSArray *loadingButtons;
NSArray *loadedButtons;
AWCustomAdWebViewAnimType transitionType;
UIWebView *webView;
UIToolbar *toolBar;
UIBarButtonItem *backButton;
UIBarButtonItem *forwardButton;
UIBarButtonItem *reloadButton;
UIBarButtonItem *stopButton;
UIBarButtonItem *linkOutButton;
UIBarButtonItem *closeButton;
}
@property (nonatomic,assign) id<AdWhirlWebBrowserControllerDelegate> delegate;
@property (nonatomic,assign) UIViewController *viewControllerForPresenting;
@property (nonatomic,retain) IBOutlet UIWebView *webView;
@property (nonatomic,retain) IBOutlet UIToolbar *toolBar;
@property (nonatomic,retain) IBOutlet UIBarButtonItem *backButton;
@property (nonatomic,retain) IBOutlet UIBarButtonItem *forwardButton;
@property (nonatomic,retain) IBOutlet UIBarButtonItem *reloadButton;
@property (nonatomic,retain) IBOutlet UIBarButtonItem *stopButton;
@property (nonatomic,retain) IBOutlet UIBarButtonItem *linkOutButton;
@property (nonatomic,retain) IBOutlet UIBarButtonItem *closeButton;
- (void)presentWithController:(UIViewController *)viewController transition:(AWCustomAdWebViewAnimType)animType;
- (void)loadURL:(NSURL *)url;
- (IBAction)back:(id)sender;
- (IBAction)forward:(id)sender;
- (IBAction)reload:(id)sender;
- (IBAction)stop:(id)sender;
- (IBAction)linkOut:(id)sender;
- (IBAction)close:(id)sender;
@end
@interface AdWhirlBackButton : UIBarButtonItem
@end
@@ -0,0 +1,266 @@
/*
AdWhirlWebBrowserController.m
Copyright 2009 AdMob, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "AdWhirlWebBrowserController.h"
#import "AdWhirlLog.h"
#define kAWWebViewAnimDuration 1.0
@interface AdWhirlWebBrowserController ()
@property (nonatomic,retain) NSArray *loadingButtons;
@property (nonatomic,retain) NSArray *loadedButtons;
@end
@implementation AdWhirlWebBrowserController
@synthesize delegate;
@synthesize viewControllerForPresenting;
@synthesize loadingButtons;
@synthesize loadedButtons;
@synthesize webView;
@synthesize toolBar;
@synthesize backButton;
@synthesize forwardButton;
@synthesize reloadButton;
@synthesize stopButton;
@synthesize linkOutButton;
@synthesize closeButton;
- (id)init {
if ((self = [super initWithNibName:@"AdWhirlWebBrowser" bundle:nil])) {
}
return self;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.webView.request) {
// has content from before, clear by creating another UIWebView
CGRect frame = self.webView.frame;
NSInteger tag = self.webView.tag;
UIWebView *newView = [[UIWebView alloc] initWithFrame:frame];
newView.tag = tag;
UIWebView *oldView = self.webView;
[oldView removeFromSuperview];
[self.view addSubview:newView];
newView.delegate = self;
newView.scalesPageToFit = YES;
[newView release];
}
self.toolBar.items = self.loadedButtons;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *items = self.toolBar.items;
NSMutableArray *loadingItems = [[NSMutableArray alloc] init];
[loadingItems addObjectsFromArray:items];
[loadingItems removeObjectAtIndex:4];
self.loadingButtons = loadingItems;
[loadingItems release], loadingItems = nil;
NSMutableArray *loadedItems = [[NSMutableArray alloc] init];
[loadedItems addObjectsFromArray:items];
[loadedItems removeObjectAtIndex:5];
self.loadedButtons = loadedItems;
[loadedItems release], loadedItems = nil;
}
- (void)viewDidDisappear:(BOOL)animated {
if (self.delegate) {
[delegate webBrowserClosed:self];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return [viewControllerForPresenting shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)presentWithController:(UIViewController *)viewController transition:(AWCustomAdWebViewAnimType)animType {
self.viewControllerForPresenting = viewController;
if ([self respondsToSelector:@selector(setModalTransitionStyle:)]) {
switch (animType) {
case AWCustomAdWebViewAnimTypeFlipFromLeft:
case AWCustomAdWebViewAnimTypeFlipFromRight:
self.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
break;
case AWCustomAdWebViewAnimTypeFadeIn:
self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
case AWCustomAdWebViewAnimTypeModal:
default:
self.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
break;
}
}
[viewController presentModalViewController:self animated:YES];
}
- (void)loadURL:(NSURL *)url {
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:urlRequest];
}
- (void)dealloc {
[loadingButtons release], loadingButtons = nil;
[loadedButtons release], loadedButtons = nil;
// IBOutlets were retained automatically
webView.delegate = nil;
[webView release], webView = nil;
[toolBar release], toolBar = nil;
[backButton release], backButton = nil;
[forwardButton release], forwardButton = nil;
[reloadButton release], reloadButton = nil;
[stopButton release], stopButton = nil;
[linkOutButton release], linkOutButton = nil;
[closeButton release], closeButton = nil;
[super dealloc];
}
#pragma mark -
#pragma mark UIWebViewDelegate methods
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
if ([request URL] != nil && [[request URL] scheme] != nil) {
if ([[[request URL] scheme] isEqualToString:@"mailto"]) {
// need to explicitly call out to the Mail app
[[UIApplication sharedApplication] openURL:[request URL]];
}
}
return YES;
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
self.toolBar.items = self.loadedButtons;
if (self.webView.canGoForward) {
self.forwardButton.enabled = YES;
}
if (self.webView.canGoBack) {
self.backButton.enabled = YES;
}
self.reloadButton.enabled = YES;
self.stopButton.enabled = NO;
if (self.webView.request) {
self.linkOutButton.enabled = YES;
}
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
self.toolBar.items = self.loadedButtons;
if (self.webView.canGoForward) {
self.forwardButton.enabled = YES;
}
if (self.webView.canGoBack) {
self.backButton.enabled = YES;
}
self.reloadButton.enabled = YES;
self.stopButton.enabled = NO;
if (self.webView.request) {
self.linkOutButton.enabled = YES;
}
// // extract title of page
// NSString* title = [self.webView stringByEvaluatingJavaScriptFromString: @"document.title"];
// self.navigationItem.title = title;
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
self.toolBar.items = self.loadingButtons;
self.forwardButton.enabled = NO;
self.backButton.enabled = NO;
self.reloadButton.enabled = NO;
self.stopButton.enabled = YES;
}
#pragma mark -
#pragma mark button targets
- (IBAction)forward:(id)sender {
[self.webView goForward];
}
- (IBAction)back:(id)sender {
[self.webView goBack];
}
- (IBAction)stop:(id)sender {
[self.webView stopLoading];
}
- (IBAction)reload:(id)sender {
[self.webView reload];
}
- (IBAction)linkOut:(id)sender {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[[UIApplication sharedApplication] openURL:self.webView.request.URL];
}
- (IBAction)close:(id)sender {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[viewControllerForPresenting dismissModalViewControllerAnimated:YES];
}
@end
@implementation AdWhirlBackButton
- (void)awakeFromNib {
// draw the back image
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(nil, 25, 25, 8, 0, colorspace,
kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorspace);
CGPoint bot = CGPointMake(19, 2);
CGPoint top = CGPointMake(19, 20);
CGPoint tip = CGPointMake(4, 11);
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextMoveToPoint(ctx, bot.x, bot.y);
CGContextAddLineToPoint(ctx, tip.x, tip.y);
CGContextAddLineToPoint(ctx, top.x, top.y);
CGContextFillPath(ctx);
// set the image
CGImageRef backImgRef = CGBitmapContextCreateImage(ctx);
CGContextRelease(ctx);
UIImage* backImage = [[UIImage alloc] initWithCGImage:backImgRef];
CGImageRelease(backImgRef);
self.image = backImage;
[backImage release];
}
@end
@@ -0,0 +1,31 @@
/*
UIColor+AdWhirlConfig.h
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "UIColor+AdWhirlConfig.h"
@class AdWhirlConfig;
@interface UIColor (AdWhirlConfig)
- (id)initWithDict:(NSDictionary *)dict;
@end
@@ -0,0 +1,73 @@
/*
UIColor+AdWhirlConfig.m
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file 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 "UIColor+AdWhirlConfig.h"
#import "AdWhirlConfig.h"
@implementation UIColor (AdWhirlConfig)
- (id)initWithDict:(NSDictionary *)dict {
id red, green, blue, alpha;
CGFloat r, g, b, a;
red = [dict objectForKey:@"red"];
if (red == nil) {
[self release];
return nil;
}
green = [dict objectForKey:@"green"];
if (green == nil) {
[self release];
return nil;
}
blue = [dict objectForKey:@"blue"];
if (blue == nil) {
[self release];
return nil;
}
NSInteger temp;
if (!awIntVal(&temp, red)) {
[self release];
return nil;
}
r = (CGFloat)temp/255.0;
if (!awIntVal(&temp, green)) {
[self release];
return nil;
}
g = (CGFloat)temp/255.0;
if (!awIntVal(&temp, blue)) {
[self release];
return nil;
}
b = (CGFloat)temp/255.0;
a = 1.0; // default 1.0
alpha = [dict objectForKey:@"alpha"];
CGFloat temp_f;
if (alpha != nil && awFloatVal(&temp_f, alpha)) {
a = (CGFloat)temp_f;
}
return [self initWithRed:r green:g blue:b alpha:a];
}
@end