Tuesday, October 25, 2011

Putting adds into an iOS app

Well, after taking a couple of days off after successfully *submitting* version 1.1 of the app for development, let's take a look at what involved in putting advertising into our app. I'm excited about this because I understand advertising on the iPhone (via iAd) is significantly better than that offered by Android. Either way, I'm not expecting to get rich.

Ok, let's google iAd iphone or something like that.

Ok, here we go:

http://developer.apple.com/iad/

Rich, Captivating Ads that Keep Users in Your Apps

iAd rich media ads combine the emotion of television with the interactivity of the web to deliver a unique, compelling experience like no other on a mobile device. Users can dive into immersive ads without ever leaving your app. When they tap the ad, your app pauses and with a single tap they close the ad and resume exactly where they left off in your app. And users have been delighted, spending an average of one minute interacting with iAd rich media ads.
Watch the highlight video
Generate More Revenue from Your Apps

iAd is the best way to generate revenue from your apps when compared to other mobile advertising platforms. Hundreds of iOS developers are already making more than $50,000 per quarter serving iAd rich media ads.

iAd is also easy to implement. Since it’s built into iOS, you don’t have to worry about integrating another SDK. Just decide where you want ads to appear in your app and with a minimal amount of code your app is ready to serve iAd rich media ads — Apple does the rest. We sell the ads and serve them to your app while you collect 60 percent of the advertising revenue generated.



Great. I especially like the easy to implement, built into iOS part.

Ok, let's see.

Arghh! High school kids everywhere. I've already moved once. As soon as I get set up, a new pack takes up the table next to me.

Ok, I did this:

Click through the Developer Advertising Services Agreement in iTunes Connect
The first step in joining the iAd Network is to click through the Developer Advertising Services Agreement, which can be found in the Contracts, Tax, and Banking Information module. In addition, you will be asked to set up your banking and tax information if you don't have a paid app on the App Store.




Next:

Enable your app for iAd rich media ads
Once you have clicked through the Developer Advertising Services Agreement in iTunes Connect, you can enable your app for iAd rich media ads in the Manage Your Applications module within iTunes Connect.



Ok, let's look at "Manage your appications".

Ok, before I enable them, I think I need to do something about actually creating the adds.

Here we go:

Creating banner views

Use the ADBannerView class to dedicate a portion of the screen to display banner advertisements in your user interface.

Once created, a banner view automatically downloads new iAd rich media ads to display to your users. View the following resources to learn how to create banner views in your app.



Ok, so it's the AddBannerView class I'm looking for.


Wow - if I click through to the video, there are like 105 of them. Oh, there's one for in-app purchases. Sweet. It's all at this url:

http://developer.apple.com/videos/wwdc/2011/?id=505

Well, I don't have the bandwidth here at the cafe to view them, so, let's look for text links.

Here's one:

http://answers.oreilly.com/topic/1747-how-to-implement-iad-on-your-iphone-applications/

With the introduction if iOS 4, Apple have also introduced iAds, a mobile advertising platform that aims to convey a new concept of interactive marketing on your smart-device. Through CSS3 and multi-touching, you will get a WebKit-powered framework to deliver optimal user experience right within your app. This layer in fact sits on top of your application, so it won’t use your app-reserved memory, as well as not leaving the app when the user interacts with the ad, but rather displayed on top of it.


Putting Ads in your app

The ADBannerView is the core class within this framework. which is simply a view and should be part of the view controller, that you have in your app.

// Ok, this is important (above)

This class manages and retrieves and displays the ads from the iAd network, managing the user interaction. The only thing you need to worry about is:

placement of the banner within your view controller; // ok
respond to networking issues (this will be discussed later); // ok

So in Interface Builder, you drag onto your view controller, the Ad BannerView, the same way you would add any other view in IB. In XCode, you make sure to add the iAd framework to your list of frameworks.

// Good, makes sense. I've been doing stuff in iB.

Working with the Banner view lifecycle

OK, so you have the banner, the next thing to concern yourself with is the managing of connectivity and various inventory changes that might occur throughout the user experience.

That is, the banner queries the iAd network for a new ad (inventory content), and this depends on connectivity. ADBannerView may not always have content in it, because you may not have any network signal on your iPhone, you may have your phone in Airplane mode.

// ok

So the two lifecycle states you have is managed through the ADBannerViewDelegate callbacks:

bannerViewDidLoadAd - Has ad content.
// ok

bannerView:didFailToReceiveAdWithError - When you have network issues and it failed to load the ad during it’s cycle. You also may not have any inventory because of how set up your ad targeting, where there is no ads based on your filter settings.

// ok

So, if we do get a failure, which is not a real error, but just something to let you know that you perhaps would not want to have an empty box, allowing you to hide (place offscreen) and back on screen when you do have content. Space is prime real-estate in the mobile world. An example of how to do this:

#pragma mark -
#pragma mark ADBannerViewDelegate methods

(void)bannerView:(ADBannerView *)bannerdidFailToReceiveAdWithError: (NSError *)error
{
//hide banner
[self moveBannerFromScreen];
}


(void)bannerViewbannerdidLoadAd: (AdBannerView *)banner
{
//show when we have content
[self moveBannerBackOn];
}

(void)moveBannerBackOn
{
//bring back to frame
CGRect theBannerFrame = self.bannerView.frame;
theBannerFrame.origin.y = self.view.frame.size.height - theBannerFrame.size.height;

//shrink existing table
CGRect originalTableFrame = self.tableView.frame;
CGFloat newTableHeight = self.view.frame.size.height - theBannerFrame.size.height;
CGRect newTableFrame = originalTableFrame;
newTableFrame.size.height = newTableHeight;

self.tableView.frame = newTableFrame; //you may want to animate this
self.bannerView.frame = theBannerFrame;

}

(void)viewDidLoadAd {
...
//hide at start until you know you get ad
[self moveBannerFromScreen];
...
}

// I guess viewDidLoadAd is different than bannerViewdidLoadAdd

Responding to actions

OK now you are seeing the ad. The ideal thing to do is reduce activity in your app (pause action when the ad is showing), and to ensure the best experience for the user when viewing the ad. Also you should save minimal state (i.e the tab you are on, rather than content), and when the ad is complete, resume the ap.

In ADBannerViewDelegate, when a user action begins on the ad (you pausing your app) you get the following callback:


- (BOOL) bannerViewActionShouldBegin: (ADBannerView *)banner willLeaveApplication: (BOOL)willLeave
{
//pause your app here
...
return yes;
}

//When the user comes back you get the callback:
- (BOOL) bannerViewActionDidFinish: (ADBannerView *)banner
{
//resume your app here
...
return yes;
}



And there you have it. For more on iAds and the iAd framework, please visit the Apple Developer Centre for documentation and sample code.




Ok. Sounds good. It's based on the concept of the whole ViewController / Delegate thing.

Here's another one:

http://jamesjennin.gs/post/759225411/the-5-minute-guide-to-implementing-iad-correctly


“But James,” my lone reader asks themselves, “is it even possible in implement iAd incorrectly?” Certainly, dear reader. In fact, Apple made it very easy to do so. See, the iAd banner class (ADBannerView) is right there in the Interface Builder library, so a naive programmer (like me) might just drag that into the interface, rebuild, code sign, deploy."

Ok, this is good. It's not going to be that easy, but it looks pretty easy at this point.

Ah, here's the problem. You might get this if you submit your app:

“We noticed that your app, Privacy for Facebook, is displaying an empty iAd banner when ad content is not available. The banner within the app should be hidden whenever ad content is not being served by iAd.”

So, hiding the window isn't optional.

Basically, displaying a blank banner is a no-no. There are a couple reasons why banners may not be displayed: they haven’t rolled out or aren’t available in a particular locale, there is no ad inventory available for your specific app, or there could just be a network issue. Apple wants you to make sure you never show blank banners.



So here’s a quick and dirty way of doing it correctly (assuming a portrait orientation, landscape is left as an exercise for the reader):



1. Add an ADBannerView to your interface, but just off screen. In this example, the ad should be at the bottom of the interface, so the origin of the ADBannerView is 0,460.

Ok. So, the height is presumably 460.

2. Set the view controller as the ADBannerView’s delegate.

Ok, that's good. I can just use whatever the regular view controller is as the app delegate.

Make sure you’ve included the iAd framework in the view controller’s .h file:
3. #import

4. Have the view controller implement ADBannerViewDelegate, and add a bool bannerIsVisible; to the interface


- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
if (!bannerIsVisible)
{
NSLog(@"bannerViewDidLoadAd");
[UIView beginAnimations:@"animateAdBannerOn" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0, -50);
buttonFrame.frame = CGRectOffset(buttonFrame.frame, 0, -50);
web.frame = CGRectMake(web.frame.origin.x,
web.frame.origin.y,
web.frame.size.width,
web.frame.size.height-50);
[UIView commitAnimations];
bannerIsVisible = YES;
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (bannerIsVisible)
{
NSLog(@"bannerView:didFailToReceiveAdWithError:");
[UIView beginAnimations:@"animateAdBannerOff" context:NULL];
// assumes the banner view is at the top of the screen.
banner.frame = CGRectOffset(banner.frame, 0, 50);
buttonFrame.frame = CGRectOffset(buttonFrame.frame, 0, 50);
web.frame = CGRectMake(web.frame.origin.x,
web.frame.origin.y,
web.frame.size.width,
web.frame.size.height+50);
[UIView commitAnimations];
bannerIsVisible = NO;
}

}

Ok. This is great. I'm just going to patch this code right in, and see what happens.

Ok, I just added the banner view to the start screen. Perfect. It's off the visual display - out of sight, out of mind.

Wait, I don't get step 2 - how to set the view controller as the delegate. I did it for the UIPicker, but I don't get how the other part works.

I just found and example that does this:

adView.delegate=self;

Ok, so if I do the import (next step) first, I can then do this:

IBOutlet ADBannerView *bannerView;

Here's the previous step for adding the import:

#import

Ok, now just connect it.

And then add this line on the viewDidLoad:

bannerView.delegate=self;

Ok, well whatever pieces I'm reducing to fit the ad in aren't the same ones in the post. I just need to figure out if I need to reduce the UIView and the image, or maybe just the image. I'll pick this up later.

Ok, here's what I ended up doing. Most of the recommendations seemed to have using CGIRectOffset, to move the banner up or down , like so:

// This moves the banner up 50 pixels
banner.frame = CGRectOffset(banner.frame, 0, -50);

// This moves the banner down 50 pixels
banner.frame = CGRectOffset(banner.frame, 0, 50);

The problem I had with it was using IBuilder to place the original banner where I wanted it. Since the background image is longer than the 480 (or 460) due to the fact that doing it like that was the only way I could get it to not display the top of the background image, just putting it below that wasn't any good - moving it up 50 wouldn't move it up all the way.

So I decided to just start it out at the *viewable* position. This way I could fit it precisely where I wanted to on the image. To move it to the correct position every time, I just saved the original frame on the viewDidLoad for the delegate, and then did the following on - (void)bannerViewDidLoadAd:(ADBannerView *)banner

{
NSLog(@"StartController, bannerViewDidLoadAd called");
if (!self.bannerIsVisible)
{
[UIView beginAnimations:@"animateAdBannerOn" context:NULL];
// banner is invisible now and moved onto the screen on 365 px
banner.frame = originalAdFrame;

[UIView commitAnimations];
self.bannerIsVisible = YES;
}
}


This assured that it would be placed in the original position on a viewable add.

On the

- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error

method, it seemed like no matter what I did, it was invisible anyway. So, just play it safe, I move it down 50, using the original frame as reference:


- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
NSLog(@"StartController, didFailToReceiveAdWithError called");

if (self.bannerIsVisible)
{
[UIView beginAnimations:@"animateAdBannerOff" context:NULL];

CGRect newBannerFrame = originalAdFrame;

int xVal = newBannerFrame.origin.x;
int yVal = newBannerFrame.origin.y;

newBannerFrame.origin.y = yVal + 50;

banner.frame = newBannerFrame;

[UIView commitAnimations];
self.bannerIsVisible = NO;
}
}

No comments:

Post a Comment