It’s not complete yet, but the basics work, so here’s my effort at building a MonoTouch binding for AdMob. This is my first attempt at making a MonoTouch binding to an Objective-C type, so please make suggestions.

Follow these MonoTouch-specific instructions adapted from AdMob’s wiki page. The paragraph numbers correspond to their instructions.

(6) The AdMobView class works except for the Version property. I don’t know why it’s sending the message to the AdMobViewInternal class and so getting an unrecognized selector.

using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
using MonoTouch.UIKit;
namespace AdMob
{
[Register ("AdMobView")]
public class AdMobView : UIView
{
static Selector selInit = new Selector("init");
static Selector selRequestAdWithDelegate =
new Selector("requestAdWithDelegate:");
static Selector selRequestFreshAd =
new Selector("requestFreshAd");
static Selector selVersion = new Selector("version");
[Export ("init")]
public AdMobView()
: base(NSObjectFlag.Empty)
{
Handle = Messaging.IntPtr_objc_msgSend(
this.Handle, selInit.Handle);
}
// This constructor must be present so that
// MonoTouch can create instances of this type
// from Objective-C code.
public AdMobView (IntPtr handle)
: base(handle)
{
}
/**
* Initiates an ad request and returns a view that will
* contain the results; the delegate is alerted when the
* ad is ready to display (or has failed to load); this is
* a good opportunity to attach the view to your
* hierarchy. If you already have a AdMobView with an
* ad loaded, and simply want to show a new ad in the
* same location, you may use -requestFreshAd instead
* (see below).
*
* This method should only be called from a run loop in
* default run loop mode. If you don't know what that
* means, you're probably ok. If in doubt, check whether
* ([[NSRunLoop currentRunLoop] currentMode] ==
* NSDefaultRunLoopMode).
*/
public static AdMobView RequestAdWithDelegate(
AdMobDelegate Delegate)
{
// Get class type
Class adMobViewClass = new Class("AdMobView");
return (AdMobView) Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend_IntPtr(
adMobViewClass.Handle,
selRequestAdWithDelegate.Handle,
Delegate.Handle));
}
/**
* Causes an existing AdMobView to display a fresh ad.
* If an ad successfully loads, it is animated in with a
* flip; if not, this call fails silently and the old ad
* remains onscreen.
*
* Note that, during the flip, views under the AdMobView
* will be exposed.
*
* To preserve the user experience, we recommend loading
* fresh ads no more frequently than once per minute.
*/
public virtual void RequestFreshAd()
{
Messaging.void_objc_msgSend(
this.Handle, selRequestFreshAd.Handle);
}
/**
* Returns the version of the current SDK.
*/
public virtual string Version
{
get
{
return ((NSString) Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(
this.Handle,
selVersion.Handle))).ToString();
}
}
}
}

(7) This AdMobDelegate class is unfinished:

using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
using MonoTouch.UIKit;
namespace AdMob
{
[Register("AdMobDelegate")]
public class AdMobDelegate : NSObject
{
public delegate void AdReceivedDelegate (AdMobView adView);
public event AdReceivedDelegate AdReceived;
public delegate void AdReceiveFailedDelegate (AdMobView adView);
public event AdReceivedDelegate AdReceiveFailed;
private static Selector selInit = new Selector("init");
[Export ("init")]
public AdMobDelegate()
: base(NSObjectFlag.Empty)
{
Handle = Messaging.IntPtr_objc_msgSend(this.Handle, selInit.Handle);
}
// This constructor must be present so that MonoTouch
// can create instances of this type from Objective-C code.
public AdMobDelegate (IntPtr handle)
: base(handle)
{
}
// Use this to provide a publisher id for an ad request. Get a publisher id
// from http://www.admob.com
private NSString myPublisherID;
public virtual NSString PublisherId
{
[Export ("publisherId")]
get { return myPublisherID; }
set { myPublisherID = value; }
}
// Sent when an ad request loaded an ad; this is a good opportunity to add
// this view to the hierachy, if it has not yet been added.
// Note that this will only ever be sent once per AdMobView, regardless of whether
// new ads are subsequently requested in the same AdMobView.
[Export ("didReceiveAd:")]
public virtual void DidReceiveAd (AdMobView adView)
{
if (AdReceived != null)
AdReceived (adView);
}
// Sent when an ad request failed to load an ad.
// Note that this will only ever be sent once per AdMobView, regardless of whether
// new ads are subsequently requested in the same AdMobView.
[Export ("didFailToReceiveAd:")]
public virtual void DidFailToReceiveAd (AdMobView adView)
{
if (AdReceiveFailed != null)
AdReceiveFailed (adView);
}
// Specifies the ad background color, for tile+text ads.
// Defaults to [UIColor colorWithRed:0.443 green:0.514 blue:0.631 alpha:1], which is a chrome-y color.
// Note that the alpha channel in the provided color will be ignored and treated as 1.
// We recommend against using a white or very light color as the background color, but
// if you do, be sure to implement adTextColor and useGraySpinner.
// Grayscale colors won't function correctly here. Use e.g. [UIColor colorWithRed:0 green:0 blue:0 alpha:1]
// instead of [UIColor colorWithWhite:0 alpha:1] or [UIColor blackColor].
private UIColor adBackgroundColor;
public virtual UIColor AdBackgroundColor
{
[Export ("adBackgroundColor")]
get { return adBackgroundColor; }
set { adBackgroundColor = value; }
}
// Specifies the primary text color for ads.
// Defaults to [UIColor whiteColor].
private UIColor primaryTextColor;
public virtual UIColor PrimaryTextColor
{
[Export ("primaryTextColor")]
get { return primaryTextColor; }
set { primaryTextColor = value; }
}
// Specifies the secondary text color for ads.
// Defaults to [UIColor whiteColor].
private UIColor secondaryTextColor;
public virtual UIColor SecondaryTextColor
{
[Export ("secondaryTextColor")]
get { return secondaryTextColor; }
set { secondaryTextColor = value; }
}
// When a spinner is shown over the adBackgroundColor (e.g. on clicks), it is by default
// a white spinner. If this returns YES, a gray spinner will be used instead,
// which looks better when the adBackgroundColor is white or very light in color.
/* - (BOOL)useGraySpinner;
// Whether AdMob may use location information. Defaults to NO.
// We ask that you respect your users' privacy and only enable location requests
// if your app already uses location information.
// Note that even if this is set to no, you will still need to include the CoreLocation
// framework to compile your app; it will simply not get used. (It is a dynamic
// framework, so including it will not increase the size of your app.)
- (BOOL)mayAskForLocation;
// If you have location information available for the user at the time that you
// make the ad request, you may provide it here (and it is recommended that you do
// so, to improve user experience and preserve battery life). If this method is implemented,
// AdMob will not request location information from the OS, even if the method returns
// nil (which it should if the user's location is not known); if this method is not
// implemented, then AdMob will request location information directly from the OS.
//
// If mayAskForLocation (above) is not implemented, or returns NO, this will not be called
// and may be completely ignored.
- (CLLocation *)location;
// If implemented, lets you specify whether to issue a real ad request or a test
// ad request (to be used for development only, of course). Defaults to NO.
- (BOOL)useTestAd;
// If implemented, lets you specify the action type of the test ad. Defaults to @"url" (web page).
// Does nothing if useTestAd is not implemented or returns NO.
// Acceptable values are @"url", @"app", @"video", @"itunes", @"call", @"canvas".
// Normally, the adservers restricts ads appropriately (e.g. no click to call ads for iPod touches).
// However, for your testing convenience, they will return any type requested for test ads.
- (NSString *)testAdAction;
// The following functions, if implemented, provide extra information
// for the ad request. If you happen to have this information, providing it will
// help select better targeted ads and will improve monetization.
//
// Keywords and search terms should be provided as a space separated string
// like "iPhone monetization San Mateo". We strongly recommend that
// you NOT hard code keywords or search terms.
//
// Keywords are used to select better ads; search terms _restrict_ the available
// set of ads. Note, then, that providing a search string may seriously negatively
// impact your fill rate; we recommend using it only when the user is submitting a
// free-text search request and you want to _only_ display ads relevant to that search.
// In those situations, however, providing a search string can yield a significant
// monetization boost.
//
// For all of these methods, if the information is not available at the time of
// the call, you should return nil.
- (NSString *)postalCode; // user's postal code, e.g. "94401"
- (NSString *)areaCode; // user's area code, e.g. "415"
- (NSDate *)dateOfBirth; // user's date of birth
- (NSString *)gender; // user's gender (e.g. @"m" or @"f")
- (NSString *)keywords; // keywords the user has provided or that are contextually relevant, e.g. @"twitter client iPhone"
- (NSString *)searchString; // a search string the user has provided, e.g. @"Jasmine Tea House San Francisco"
// You can control the appearance of the AdMob mini-browser and the nav bars
// to fit with the rest of your app. See the documentation for UIToolbar
// and UINavigationBar for details. Defaults to standard iPhone chrome.
- (UIBarStyle)embeddedWebViewBarStyle;
- (UIColor *)embeddedWebViewTintColor;
// Sent just before presenting the user a full screen view, such as a canvas page or an embedded webview,
// in response to clicking on an ad. Use this opportunity to stop animations, time sensitive interactions, etc.
- (void)willPresentFullScreenModal;
// Sent just after dismissing a full screen view. Use this opportunity to
// restart anything you may have stopped as part of -willPresentFullScreenModal:.
- (void)didDismissFullScreenModal;
*/
}
}

I’m a MonoTouch noob (like everybody else), so I could be way off here, but I think you’d want to create the NSString using its IntPtr constructor. So (I’m splitting this into a couple lines for clarity):

Is it possible for someone to publish a working version of this? I have been trying to implement this but am at a dead end. I have a complicated news reader using a tab controller with navigation controllers within the tabs so that I can navigate to stories. I have been unable to implement even a simple applciation with this ad controller :S. Anyone?

I had to change the RequestAdWithDelegate interface to use selInit.Hand instead of selRequestAdWithDelegate.Handle. I’m not sure that worked. However, it next threw an error on the advertView.Frame =xxx. I tried setting it in the delegate.AdReceived… but still no success.

Has anyone made any headway beyond these posts from late October? On an unmodified version of the sample project, I too get the “unrecognized selector” exception on requestAdWithDelegate that ChadR talked about…although it seems to me that replacing the selector binding for that method with selInit.Handle would simply re-call the “init” method and that requestAdWithDelegate would never get called…

Thanks for the quick reply! After some more perseverance, I found that the problem both ChadR and I were having is related to the additional mtouch arguments in the .csproj file being housed within a node called “ExtraMtouchArgs”. However the latest version of MonoDevelop places them within a node called “MtouchExtraArgs”. After removing the first node from the project file, and re-specifying the arguments using the Project Options dialog, everything ran perfectly.

Thanks again for your work on this, and the heads up that it’s not working on the hardware. I’ll follow up with you if we find a workaround for that one.

Thanks again! This is extremely helpful. Do you know what the difference is between specifying the “NoThumbs” versions of the AdMob files? Under the “Debug/iPhone” configuration, specifying the “NoThumbs” version does not compile, but when I specify the “regular” version, it succeeds…

I just meant that compiling the project itself would fail with “no mtouch output” or a similar error….however I later realized that the case for the folder “AdMob” was wrong in the argument (it was set at “admob”) and once that was fixed everything built and deployed to the device perfectly. It’d be very interesting to see if anyone knows what the NoThumb version actually does under the hood to make it all work.

Just wondered if you’re able to successfully deploy this under the “Release – iPhone” configuration? The project deploys to the device just fine for me under the Debug config, but using the same mtouch args under the Release one fails…I get:

Does the project successfully build and deploy to the device, even though you get those same messages? For me it does not…only under Debug config will it successfully upload. Do you get those messages under both Debug and Release configs for the device? Or just under Release?

The MonoTouch project, http://www.sabonrai.com/downloads/MT_SampleAdMob.zip, is a working example. All four configuration combinations of Debug|Release and iPhone|Simulator work. In all cases, they show the same error/warning messages identified in my previous comment.

This updated version of the project corrects the mtouch extra arguments. They should be as follows for Simulator:

Dumb question since I don’t know what you’re doing: are you building for iPad? Minimum version of 3.2 applies only to iPad. I’ve not built this for iPad so I don’t know what issues you might run into. If you’re not using iPad, I suggest setting your minimum OS version to 3.0 if you want to support older version of the OS and then you’ll have to download that SDK. Set your base SDK to 4.0 (or 4.0.1) so you can support the current version of the OS.

Thanx for the MT_SampleAdMob project. We really needed some clever guy to shine his light on this prob 🙂

When I try to build it (Debug for the Simulator, latest xcode and monotouch), the main compilation goes without probs, but the ‘Compiling to native code’ phase hangs without any output. When stopping it, it rightfully complains ‘mtouch failed wit no output (137)’

I have now 3 libraries I could use. The three are
1) the original libAdMobSimulator3_0.a that is in the http://www.sabonrai.com/downloads/MT_SampleAdMob.zip file, and the
2) libAdMob.a and
3) libAdMobNoThumb.a libraries from the latest admob_iphone_sdk_20100908.tar.gz.

All three libraries build and give the same test results (cfr later). I do not know which one I should use and why.

Anyhow, the app crashes at the first access of the AdMobView class. It does not print any message, it just crashes.

To my surprise, it does this some 14540 times, at what point the app just stops. I do not understand why this is called so many times. The last 5 lines are:

Version 14536 class=MonoTouch.ObjCRuntime.Class
Version 14537 class=MonoTouch.ObjCRuntime.Class
Version 14538 class=MonoTouch.ObjCRuntime.Class
Version 14539 class=MonoTouch.ObjCRuntime.Class
Version 14540 class=MonoTouch.ObjCRuntime.Class

I don’t know if this might be helpful, but at least, it did not expect this behavioiur and it is a symptom of what is going wrong.