iAD with Monotouch

by ManniAT 4. July 2010 20:07
Technorati-Tags: ,,

Working on my RPS project (http://iphone.pp-p.net/) I decided (at a late moment) to implement iAd.

But let’s start from the beginning. The design goal for this app was to build a game which can be played with nearby players as well as over the internet.

So my first approach was to implement a form which allows me to pick peers. The result – a lot of “double entries” or only one side seeing the other and things like this.
So the next decision was – 2 forms – one for the internet and for gamekit I’ll use the GKPeerPickerController.

Unfortunately two things happened:

  1. GKPP is also showing double entries (or nothing sometimes)
  2. GKPP force me to turn on Bluetooth

So the problem became even worse – and I decided to go back to my own implementation.
The first approach was to subclass a UIAlertView (which works well) but later the iAD framework took my attention. The idea – it’s could be a boring  situation (waiting for matching players) and that’s from my point of view a good place to show an add which doesn’t annoy the user too much.

But iAD needs a UIViewController – it doesn’t work when you host it in a UIAlertView.
So I changed the things to a “normal” UIViewController which I simply push when needed.

It looks like this:

4List IMG_0331

 

As you can see – the second version shows an add.
My first problem – I couldn’t get the thing running. Messing around for about an hour I got stuck providing format information. My (typical) reaction – joining the MonoTouch IRC channel – and ask stupid questions.

And (within minutes) “kangaroo” confirmed a bug – and help me implementing a workaround.
That’s what I like most with MonoTouch – you have a problem – and get it fixed real fast.
By the way – I had only little problems – and some of them have been my fault.

Anyhow – the documentation about the iAd framework is a bit poor – so I decided to write this post.
To come to a point – after “fixing” the bug (a property returns null) it took me about 2 minutes to implement what you see above – an add at the bottom of my UI.

Here is the relevant code:

Snippet created with CBEnhancer
public class Application {
    static void Main(string[] args) {
        Globals.IsOnOS4 = UIDevice.CurrentDevice.RespondsToSelector(new Selector("isMultitaskingSupported"));
        if(Globals.IsOnOS4) {
            Globals.IsMultitaskingEnabled = UIDevice.CurrentDevice.IsMultitaskingSupported;
        }
        Console.WriteLine("OS4: " + Globals.IsOnOS4.ToString() + " Multi: " + Globals.IsMultitaskingEnabled.ToString());
        UIApplication.Main(args);
    }
}

 

My project is a universal app – so I placed this code in Main.cs – you could also place something like this in you AppDelegate… file at FinishedLaunching.

“Globals” is a static class which holds some information I need all around the project.

Now to the iAd related code in the UIViewController:

Snippet created with CBEnhancer
00 private object m_adBannerView;
01 
02 public override void ViewDidLoad() {
03     base.ViewDidLoad();
04     //boring stuff
05     if(Globals.IsOnOS4) {
06         m_adBannerView = new ADBannerView();
07         ADBannerView adBannerView = m_adBannerView as ADBannerView;
08         NSMutableSet nsM = new NSMutableSet();
09         nsM.Add(new NSString("ADBannerContentSize320x50"));
10         adBannerView.RequiredContentSizeIdentifiers = nsM;
11         adBannerView.AdLoaded += new EventHandler(m_adBannerView_AdLoaded);
12         adBannerView.FailedToReceiveAd += new EventHandler<AdErrorEventArgs>(m_adBannerView_FailedToReceiveAd);
13         adBannerView.Frame = new RectangleF(0, m_uivInner.Frame.Bottom + 9, 320, 50);
14         View.AddSubview(adBannerView);
15         adBannerView.Hidden = true;
16     }
17 }
18 
19 void m_adBannerView_AdLoaded(object sender, EventArgs e) {
20     (m_adBannerView as ADBannerView).Hidden = false;
21 }
22 void m_adBannerView_FailedToReceiveAd(object sender, AdErrorEventArgs e) {
23     (m_adBannerView as ADBannerView).Hidden = true;
24 }

 

First I declared the m_adBannerView – since I was a bit scared if it could make problems on “prior iOS 4” systems I declared it as object.
This explains the code in line 07 – where I use a local variable to prevent me from permanent casting.

Line 09 – a set to tell the AddBannerView which formats I support (the constant in line 09 is because of the bug).
Then two methods I need to implement – AdLoaded (called when an ad is available) and FailedtoReceiveAd.
The second method (although the event parameter is “..Error…”) is nothing more than an information that no ad is there (no matching ad in the inventory, no internet connection, …)

And for the ones curious about line 13 – this m_uivInner is a childview in the blue rectangle which holds buttons, the list and so on.
I use this subview since the same thing is also used on the iPad – but with a different size / location.

Anyhow – the code does 3 very simple things:

  1. It creates the ADBannerView  - telling it that I support portrait mode only (…320x50)
    It adds this view to my UI and hides it
  2. …AdLoaded displays the view
  3. …FailedToReceiveAd hides the view again

Of course I could have used an inline delegate – but I like methods – and these to guys will get some extra code to animate the things. So having the methods isolate gives me more isolation (primarily optical).

Snippet created with CBEnhancer
void m_adBannerView_FailedToReceiveAd(object sender, AdErrorEventArgs e) {
        float fZoom = 0.45f;
        float fAngle = 45;

        UIView.BeginAnimations("HideAdStep1");
        UIView.SetAnimationDelegate(this);
        UIView.SetAnimationCurve(UIViewAnimationCurve.EaseIn);
        UIView.SetAnimationDuration(0.2);
        CGAffineTransform ctZoom = CGAffineTransform.MakeScale(fZoom, fZoom);
        ctZoom.Rotate(ToRadians(fAngle));
        (m_adBannerView as ADBannerView).Transform = ctZoom;
        (m_adBannerView as ADBannerView).Alpha = fZoom;
        UIView.SetAnimationDidStopSelector(new Selector("DoHideAdStep2"));
        UIView.CommitAnimations();
    }
    [Export("DoHideAdStep2")]
    private void DoHideAdStep2() {
        UIView.BeginAnimations("HideAdStep2");
        UIView.SetAnimationDelegate(this);
        UIView.SetAnimationCurve(UIViewAnimationCurve.EaseOut);
        UIView.SetAnimationDuration(0.1);
        (m_adBannerView as ADBannerView).Alpha = 0;
        UIView.CommitAnimations();
    }

 

This is just a simple example – it turns the add (45°) – makes it smaller – and in step 2 it hides it by setting alpha to 0. The reverse thing is done in AdLoaded.

There are other events for the ADBannerView you might be interested.
The ActionFinished (tells you that the user closed the “banner dialog”). This is also available as event on the ADBannerView.
The second thing is (unfortunately not available as event) ActionShouldBegin. To handle this you have to implement you own delegate (just overriding this single method).

In my case I don’t care – a user watches gets bored and clicks the ad. The iAd guide says I should (!!!) disable sounds, animation or other activities that require user interaction.

That’s (almost) what I do – except – if someone invites the user while he watches the ad content I notify him with a sound. My understanding of the iAd guide makes me feel that this is ok.

Manfred

I attached a little sample showing the things.
The iAdTest$.. project is the VS project - the one without the $ signs the MT project.

iAdTest.zip (13.84 kb)

Tags: , ,

iPhone | MonoTouch

Comments (2) -

7/7/2010 12:26:14 AM #

Dean Harry

Hi Manfred,

I follow your post and ran into some trouble. I created a very basic screen and put your code in however it wont run. It gets to the line adBannerView.RequiredContentSizeIdentifiers = nsM; and just stops. No errors in the Application Output, the program simply stops.

Any ideas why it would do that?

Dean

Dean Harry Australia | Reply

7/7/2010 9:11:40 AM #

ManniAT

I attached a working project - maybe this can help you.
Find it at the end of the post.

ManniAT Austria | Reply

Pingbacks and trackbacks (2)+

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading


Powered by BlogEngine.NET 2.0.0.0