Getting iAds working in 2.1

Hi all

My apps keep getting rejected because of the camera access bug in 2.0, so I’m forced to use the 2.1 runtime… but now the existing add-ons no longer work in 2.1 so it has completely stopped me in my tracks, most specifically the iAds add on.

iAds are a big part of apps that are released on the iOS store, so having no working iAds add-on is kind of a big deal. @Simeon made it sound like it’s easy to get the existing add-ons working in 2.1, but I can’t seem to figure it out. So I was thinking maybe we can collectively try to figure out how to get the existing iAds add-on working in 2.1, since I’m sure a lot of use are planning on using the iAds in our apps.

I’m posting the existing iAds add-on below, and I will keep trying to mess with it and figure out how to get it to work with 2.1. Hopefully anyone else trying to get iAds to work can try to figure it out also, and maybe we can come up with a iAds add-on that works with 2.1.

I suck with objective-c so it may be a super simple fix…

Here is the existing iAds add-on:

iAdsaddon.h



//
//  IAdsAddOn.h
//  30 Balls
//
//  Created by Théo on 6/19/14.
//  Copyright (c) 2014 MyCompany. All rights reserved.
//

#import "CodeaAddon.h"
#import <iAd/iAd.h>
#import <Foundation/Foundation.h>

// Device Detection Macros - can be used to position the banner advertisement based on device.
// Not used in this tutorial.

//#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
//#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
//#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0f)
//#define IS_IPHONE_4 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0f)

//  Create a variable which points to the instance of this class so that we can access self
//  from within the Lua c functions.
////
id iAdsAddOnInstance;

//  This class conforms to the CodeaAddon & ADBannerViewDelegate Protocols

@interface IAdsAddOn : NSObject<CodeaAddon, ADBannerViewDelegate>

@property BOOL isBannerVisible;
@property BOOL showBannerFromTop;
@property BOOL adsAllowed;
@property (strong, nonatomic) ADBannerView *bannerView;
@property (weak, nonatomic) CodeaViewController *currentController;

//  Forward declare our Lua iAd functions. These are static to confine their scope
//  to this file. By default c functions are global.

static int showAdFromTop(struct lua_State *state);
static int showAdFromBottom(struct lua_State *state);
static int hideAd(struct lua_State *state);

@end

IAdsAddOn.m



//
//  IAdsAddOn.m
//  30 Balls
//
//  Created by Théo on 6/19/14.
//  Copyright (c) 2014 MyCompany. All rights reserved.
//

#import "lua.h"
#import "IAdsAddOn.h"

@implementation IAdsAddOn

#pragma mark - Initialisation

- (id)init
{
    self = [super init];
    if (self)
    {


        //  audioAddOnInstance allows us to access self from within the c functions.

        iAdsAddOnInstance = self;

        // Initialise our Instance Variables

        _isBannerVisible = NO;
        _showBannerFromTop = YES;
        _adsAllowed = NO;

        //  Initialise our iAd Banner View

        CGRect frame = CGRectZero;
        //frame.size = [ADBannerView sizeFromBannerContentSizeIdentifier: ADBannerContentSizeIdentifierPortrait];

        _bannerView = [[ADBannerView alloc] initWithFrame: frame];
        //_bannerView.requiredContentSizeIdentifiers = [NSSet setWithObject: ADBannerContentSizeIdentifierPortrait];
        [_bannerView setAutoresizingMask: UIViewAutoresizingFlexibleWidth];
        _bannerView.delegate = self;
    }
    return self;
}

#pragma mark - CodeaAddon Delegate

//  Classes which comply with the <CodeaAddon> Protocol must implement this method

- (void) codea:(CodeaViewController*)controller didCreateLuaState:(struct lua_State*)L
{
    NSLog(@"iAdAddOn Registering Functions");

    //  Register the iAd functions, defined below

    lua_register(L, "showAdFromTop", showAdFromTop);
    lua_register(L, "showAdFromBottom", showAdFromBottom);
    lua_register(L, "hideAd", hideAd);

    //  Hook up with the CodeaViewController - don't try to add subviews in this method.

    self.currentController = controller;
}

#pragma mark - iAds Add On Functions and associated Methods

//  Objective C Methods

- (void)showBannerViewAnimated:(BOOL)animated
{
    if ([self.bannerView isBannerLoaded])
    {
        if (_adsAllowed) {
            //  We only display the banner View if it has ads loaded and isn't already visible.
            //  Set the banner view starting position as off screen.

            CGRect frame = _bannerView.frame;

            if (_showBannerFromTop)
                frame.origin.y = 0.0f - _bannerView.frame.size.height;
            else
                frame.origin.y = CGRectGetMaxY(self.currentController.view.bounds);

            _bannerView.frame = frame;

            // Set banner View final position to animate to.

            if (_showBannerFromTop)
                frame.origin.y = 0;
            else
                frame.origin.y -= frame.size.height;

            if (animated)
                [UIView animateWithDuration: 0.5 animations: ^{self.bannerView.frame = frame;}];
            else
                self.bannerView.frame = frame;

            _isBannerVisible = YES;
        }
        else
        {
           NSLog(@"Ads should not be shown right now");
            [self hideBannerViewAnimated: NO];




        }
    }
    else
        NSLog(@"showBannerViewAnimated: Unable to display banner, no Ads loaded.");
}

- (void)hideBannerViewAnimated:(BOOL)animated
{
    if (_isBannerVisible || !_adsAllowed)
    {
        CGRect frame = self.bannerView.frame;

        if (_showBannerFromTop)
            frame.origin.y -= frame.size.height;
        else
            frame.origin.y = CGRectGetMaxY(self.currentController.view.bounds);

        if (animated)
            [UIView animateWithDuration: 0.5 animations: ^{self.bannerView.frame = frame;}];
        else
            self.bannerView.frame = frame;

        _isBannerVisible = NO;
    }
}

//  C Functions
//
//  Note that the returned value from all exported Lua functions is how many values that function should return in Lua.
//  For example, if you return 0 from that function, you are telling Lua that function returns 0 values.
//  If you return 2, you are telling Lua to expect 2 values on the stack when the function returns.
//
//  To actually return values, you need to push them onto the Lua stack and then return the number of values you pushed on.

static int showAdFromTop(struct lua_State *state)
{

    NSLog(@"Show Ad From Top");

    [iAdsAddOnInstance setAdsAllowed: YES];
    [iAdsAddOnInstance setShowBannerFromTop: YES];
    [iAdsAddOnInstance showBannerViewAnimated: YES];

    return 0;
}

static int showAdFromBottom(struct lua_State *state)
{
    [iAdsAddOnInstance setAdsAllowed: YES];
    [iAdsAddOnInstance setShowBannerFromTop: NO];
    [iAdsAddOnInstance showBannerViewAnimated: YES];

    return 0;
}

static int hideAd(struct lua_State *state)
{
    [iAdsAddOnInstance setAdsAllowed: NO];
    [iAdsAddOnInstance hideBannerViewAnimated: YES];

    return 0;
}

#pragma mark - iAd Banner View Delegate

//  Your application implements this method to be notified when a new advertisement is ready for display.

- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
    NSLog(@"Banner View loaded Ads for display.");
    NSLog(@"Active View Controller: %@", self.currentController.class);

    //  Add our banner view to the CodeaViewController view, if we haven't already.

    if (![self.currentController.view.subviews containsObject: _bannerView])
        [self.currentController.view addSubview: _bannerView];

    [self showBannerViewAnimated: YES];
}

//  This method is triggered when an advertisement could not be loaded from the iAds system
//  (perhaps due to a network connectivity issue).

- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
    NSLog(@"bannerview failed to receive iAd error: %@", [error localizedDescription]);

    [self hideBannerViewAnimated: YES];
}

//  This method is triggered when the banner confirms that an advertisement is available but before the ad is
//  downloaded to the device and is ready for presentation to the user.

- (void)bannerViewWillLoadAd:(ADBannerView *)banner
{

}

//  This method is triggered when the user touches the iAds banner in your application. If the willLeave argument
//  passed through to the method is YES then your application will be placed into the background while the user is
//  taken elsewhere to interact with or view the ad. If the argument is NO then the ad will be superimposed over your
//  running application.

- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
    self.currentController.paused = YES;
    NSLog(@"Ad being displayed - Codea paused.");

    return YES;
}

//  This method is called when the ad view removes the ad content currently obscuring the application interface.
//  If the application was paused during the ad view session this method can be used to resume activity.

- (void)bannerViewActionDidFinish:(ADBannerView *)banner
{
    self.currentController.paused = NO;
    NSLog(@"Ad dismissed - Codea running.");
}

@end

@Crumble I updated that code to work with 2.1 and uploaded it here:

https://github.com/TwoLivesLeft/Codea-Addons/tree/master/iAd

(hopefully Théo, the original author doesn’t mind!)

Seems to work in my quick testing.

Edit: To use it, register it in your AppDelegate.mm like so:

[self.viewController registerAddon:[iAdsAddon sharedInstance]];

@Simeon, I’m the original author, I don’t mind at all, I shared it for others to use it and this will only help :slight_smile:

@JakAttak thanks for writing the original! Would you mind if this gets developed further and possibly becomes included in the Xcode export part of Codea?

(i.e., the way the example GameCenterAddon.h/m is included at the moment)

@Simeon, not at all, in fact I think that would be great

@Simeon That’s awesome, really appreciate it! Was a little over my head.

@JakAttak I didn’t know who wrote the iAds add on, appreciate you putting it out there for us to use!

@JakAttack, @Crumble & @Simeon - Many, MANY thanks guys - I’m just in the market for an iAd’s add on and the timing on this is perfect. :slight_smile:

@JakAttack, @Crumble & @Simeon Cracking work guys, thanks

@JakAttack, @Crumble & @Simeon Thanks!

Hi all, this comes just in time for my latest update.

A quick question as I’ve not used GitHub/add on, is this just code I download and put into my Xcode project or as an add on is there a way to download it to my Codea app and include it as part of my export? I ask as having that and the game centre code baked in in export sounds epic!!

(My objective C sucks too)

At the moment it isn’t included, but I imagine that it will be for 2.2.

It’s easy to implement though, you just download the iAddAddon.h and iAdsAddon.m files, drop them into your project under the add-ons > extras folder, then turn on the iAds framework under the general tab of your project.

Brilliant, thanks crumble, Simon and Jakattak

Hi I’m totally confused with this new code

I’ve turned on iAds framework, I’ve added @Simeon 's code to the AppDelegate.mm and I’ve copied the two Iads files to the addons > extras folder but in the delegate I think there’s a line of code missing as it says:
Use of undeclared identifier ‘iAdsAddon’

what am I missing?

@Majormorgan make sure when you drag and drop the iAdsAddOn files to the extras folder that you click the little box next to the project name.

Here is how my AppDelegate.mm looks, I have submitted and been approved for 5 games so far using this code, and iAds works fine. I don’t use Game Center even though its in there. Note on around line 20 one of the lines says ProjectNameHere, which you replace with the name of your project with no spaces, capitalizing the first letter of each word:


//
//  AppDelegate.mm
//

#import "AppDelegate.h"

#import "StandaloneCodeaViewController.h"

#import "GameCenterAddon.h"

#import "IAdsAddOn.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    NSString* projectPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"ProjectNameHere.codea"];
    
    self.viewController = [[StandaloneCodeaViewController alloc] initWithProjectAtPath:projectPath];
    
    [self.viewController registerAddon:[iAdsAddon sharedInstance]];
    
    //Uncomment the following line if you'd like to use the basic GameCenter addon:
    //[self.viewController registerAddon:[GameCenterAddon sharedInstance]];
    
    //See GameCenterAddon.h for the Lua API description.
    
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
}

- (void)applicationWillTerminate:(UIApplication *)application
{
}

@end


Once you add the two iAdsAddon files, change the app delegate.mm to the above, and add the iAds framework, all you have to do is change your bundle name to the App Name, Bundle Display Name to the App Name (both with spaces and have to be the same, one is the name on the store, the other is the name on the device), and Bundle Identifier to your “com.xxxxxxxxx.xxxxx” bundle identifier. Those last three are under the info tab. Finally go to the general tab, where it says team (or possibly says fix issue) click it and select your development name.

One last thing, in the middle of your general tab, you choose if the app is landscape, portrait or both.

That is everything I do and then you are ready to submit by choosing iOS device on the top toolbar, then click product > archive > submit.

That makes sense sense Crumble I just spotted they were missing in my project browser

Thanks @Crumble

I spotted that the #import “IAdsAddOn.h” was missing, just as I hadn’t dragged and dropped the two iads files into my xcode project it wasn;t linking the files were there even though I had copied them to the root directory on my mac. If I had dragged and dropped I’d have been alright. Lol

I just need to remember where I call the ads now for the top of the game

thanks
Major

Just a note, once you do manage to get your app build submitted from Xcode, you can go to iTunes connect, select the build in your app sttings where you put screenshots and everything, then click prerelease and you can do an internal test on your iPhone or iPad super easy from there. To make sure everything works. Its a new feature that makes ad hoc testing amazingly simple.

Thanks. id got previous versions with ads off the ground, but this new code is a little different.

I’m struggling to find where I set ads to throughout the game, or in key parts. Any ideas?

When I revert to an earlier xcode project (6 months ago) that one shows the test ads are working. This current one is saying in the output window ‘ads shouldn’t be showing right now’

Found it