Monday, January 17, 2011

How to Integrate iAd for OS3.2+ and Admob as Backup


I am impressed with iAd revenue given by Apple. It really surprises me. So I end up putting iAds for most of my free apps. Though, I'd like the app to be downloaded by OS3.2 users as well (wider user base). So, upon searching, I found the tutorial from Ray Wenderlich. It totally works! If your app is ran on 3.2, it will not cause a crash using this way. iAd is simply not instantiated in OS3.2.



This post is not really a step by step tutorial for the codings, but more of an explanation of what needs to be done in order to have iAd integrated in your app, with Admob as backup ad in OS3.2 and when iAd fails. Please read this post carefully. With the downloadable full project source code sample, you should be able to figure this out easily.

1. To get the Admob SDK, you need to be registered to Admob and add a new Site/Apps. Key in your app URL, and soon the Admob Publisher Code will be given and you can then download the Admob SDK built specifically for your app (basically the SDK will be pre-filled with your publisher code).

2. All you need to do is then copy 2 folders - Admob and TouchJSON into your app folder in Finder. Then drag these 2 folders in your XCode Project group. Then you need to add 5 Frameworks to your project. They are MediaPlayer, CoreGraphics, AudioToolBox, MessageUI, and QuartzCore.

3. For iAd, you need to add and weaklink the iAd.framework. Click on Targets->"App name" and get the info of it. Then go to General tab and underneath there is a list of frameworks. On the right side, there is a column called "Type". Click on the value "Required" and change to "Weak".

4. Now for the required codes to declare Admob and iAd. In .h of your viewcontroller, declare as below (read the comments in code below for more details):
#import "AdMobDelegateProtocol.h"

@class AdMobView;



@interface iAdMobViewController : UIViewController <AdBannerViewDelegate, AdmobDelegate> {

id _myAD; // we are declaring as id because OS3.2 won't know the existance of ADBannerView

AdMobView *adMobAd;

NSTimer *admobTimer;

IBOutlet UIButton *exampleBtn; // just to simulate repositioning objects

}



@property (nonatomic, retain) NSTimer *admobTimer;

@property (nonatomic, retain) id myAD;

@property (nonatomic, retain)  UIButton *exampleBtn;



-(void)createAdBannerView; // method to create iAd banner view

-(void)callAdmob; //method to create Admob view



// methods to show or hide iAd view upon receiving ad or failing to receive ad.

-(IBAction)moveAdOut; 

-(IBAction)moveAdIn;



// methods to show or hide Admob view upon receiving ad or failing to receive ad.

-(IBAction)moveAdMobOut;

-(IBAction)moveAdMobIn;



end;

Then in .m file, we need to include a header file for Admob only.
#import "AdMobView.h"

Most of the code above is pretty straight forward. Though NSTimer deserves a little explanation. Admob works a little different than iAd. For iAd, once we create the BannerView, retained it, then iOS will continue to call for adverts from Apple server every 30seconds (edit: only test iAd in SDK 4.0 is called every 30sec, actual iAd refresh is called every 3 minutes). It is done automatically. But for Admob, the SDK does not call for new ads automatically. For Admob, the ad will be called once everytime we create/alloc an AdMobView. If you see in the AdMob delegates, there is one function called requestFreshAd, though this just refresh the ad inside the view with new one WITHOUT calling the didReceiveAd delegate!

Our goal in this project is to make iAd the master ad server, and admob the secondary ad filler. So, in OS4.0, we instantiate iAd once, so the iOS will continue to send ad requests every 30 seconds. So we set the iAd to show if the ad is received, and set to create and show Admob ad if iAd fails. This cycle will continue forever. So we will be having iAd and Admob continuously showing.

Though, in OS3.2, iAd NEVER gets instantiate. So the iAd didFailToReceiveAd delegate will never get called, and that means Admob ad will never be instantiated as well! So we need to trigger the creating of Admob ad calling manually. And that's where admobTimer comes in the picture.

Testing the project can be painstaking at times. Because since we make iAd the master, and iAd Test ads fillrate is like 99%, it will take a while for Admob Test ad to appear. During running the project in simulator, monitor it together with Console so that you can see the logs every 30 seconds. Test the app with iPad Simulator 3.2 too, and it should not crash, and you should only see Admob ads in the iPad Sim3.2.

There are a few more things that is important in setting up the Admob Delegate functions.

1. The Publisher ID delegate. Key in YOUR Publisher ID in that string placeholder. (in your .m file)
- (NSString *)publisherIdForAd:(AdMobView *)adView {

return @"your admob publisher id here";  

}

2. To get the test Ads for Admob, put this delegate:
- (NSArray *)testDevices {

return [NSArray arrayWithObjects:

ADMOB_SIMULATOR_ID,                             // Simulator

nil];

}

3. To get test ads in your devices, just add your 40digits device ID as NSString into the array in the above delegate function. If you have more devices, just continue to add them to the array.
- (NSArray *)testDevices {

return [NSArray arrayWithObjects:

ADMOB_SIMULATOR_ID,                             // Simulator

@"your 40digit device ID here"

nil];

}

4. To get test ads in iAd, you don't need to do anything in Simulator. Even if you haven't added a new version with iAd enabled in iTunesConnect, you can still receive test ads in the iAds in simulator or device.