cocos2d-x iOS iAD 광고 연동

 이번 포스팅에서는 iOS App에 광고를 붙여 수익을 얻을 수 있는 iAD를 cocos2d-x와 연동을 해보겠습니다.

 TARGETS -> Build Phases -> Link Binary With Libraries에서 iAd.framework를 추가합니다.

iAd라는 Object-C class를 만드시고

///< iAd.h
#import <iAD/iAD.h>

@interface iAD : NSObject<ADBannerViewDelegate>

+ (void) init;


///< iAd.m

#import "iAD.h"

#import "EAGLView.h"

UIViewController* gAdViewController = 0;

@implementation iAD

+ (void) init
{
    ADBannerView* adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
    adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierLandscape];
    adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
    [adView setDelegate:self];
    
    gAdViewController = [[UIViewController alloc] init];

    ///< 광고뷰를 컨트롤러에 추가
    [gAdViewController.view addSubview:adView];
    ///< OpenglView 컨트롤러 추가
    [[[EAGLView sharedEGLView] window] addSubview:gAdViewController.view];
}

///< 광고를 수신받지 못했을 처리
- (void) bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
    NSLog(@"iAD didFailToReceiveAdWithError");
    [UIView beginAnimations:@"animateAdBannerOff" context:NULL];
    ///< cocos2d-x는 왼쪽 밑이 0,0이지만 UIView는 왼쪽위가 0,0 이므로 -50을 해서 화면 밖으로 보내버린다. 안하면 리젝된다고 한다.
    banner.frame = CGRectOffset(banner.frame, 0, -50);
    [UIView commitAnimations];
}
@end

 위와 같이 소스를 작업하시고 빌드 실행하시면

 어라 세로로 나옵니다. 이것은 iOS Game Center 연동할 때 그 망령이 또!? 분명 Game Center 붙이듯이 했는데 이러네요. 해결법은 간단한데요,
    [[[EAGLView sharedEGLViewwindowaddSubview:gAdViewController.view];
대신

    [[EAGLView sharedEGLView] addSubview:gAdViewController.view];

 이렇게 EAGLView해줍니다. 차이점은 Game Center는 ModalView로 처리했고, iAD는 그냥 addSubView한다는 점인데 암튼 잘 되네요.

  광고를 한번 클릭해봤습니다. 옆으로 누워서 나오긴 하지만 풀 화면으로 잘 나와주네요. 이제 x 버튼을 눌러 종료하면,

 키보드가 호출되어 있네요? 뭘 누르든 더이상 진행할 수 없습니다. 다시 실행하지 않는이상은 말이죠. 구글링을 해보니 iOS 4 이하에서는 이상이 없었는데 iOS 5에서 생긴문제라고 하네요.
http://cocos2d-x.org/boards/6/topics/8155?r=12172#message-12172
http://www.cocos2d-x.org/boards/6/topics/9968
 두 링크를 통해 해결할 수 있습니다. 결국 cocos2d-x 소스를 건들어야합니다. 2.0.1을 쓰고 있는데 최신인 2.0.4 까지의 업데이트 내역을 봐도 cocos2d-x 자체에 아직 포함이 안된듯 합니다. 정리하자면,

cocos2dx\platform\ios\EAGLView.h 파일

@interface EAGLView : UIView <UIKeyInput, UITextInput>
{
...
...
///< 변수 추가
    BOOL acceptFirstResponder_;
}
///< 프로퍼티 추가
@property(nonatomic, readwrite, assign) BOOL acceptFirstResponder;



cocos2dx\platform\ios\EAGLView.mm 파일

@implementation EAGLView
...
...
///< synthesize 추가
@synthesize acceptFirstResponder=acceptFirstResponder_;


- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples;
{
...
...
        view = self;
        ///< 추가한 변수 NO로 초기화
        acceptFirstResponder_ = NO;
...
}

#pragma mark -
#pragma mark UIView - Responder

///< becomFirstResponder 오버라이딩
- (BOOL)becomeFirstResponder {
if ( acceptFirstResponder_ ) {
return [super becomeFirstResponder];
}
return NO;
}


cocos2dx\platform\ios\CCEGLView.mm 파일

void CCEGLView::setIMEKeyboardState(bool bOpen)
{
    if (bOpen)
    {
        ///< 추가한 변수 YES로 세팅
        [[EAGLView sharedEGLView] setAcceptFirstResponder:YES];
        [[EAGLView sharedEGLView] becomeFirstResponder];
        ///< 추가한 변수 NO로 세팅
        [[EAGLView sharedEGLView] setAcceptFirstResponder:NO];
    }
...
}

 위와같이 cocos2d-x 소스 변경후 하시면 키보드는 더이상 나오지 않습니다. iOS딴에서 UIView가 사라지면서 becomFirstResponder 호출될 때는 추가한 변수가 NO라서 키보드가 안 나오고, 개발자가 명시적으로 setIMEKeyboardState를 사용해 키보드를 호출할 때는 YES로 세팅 후 진행하므로 키보드가 나오게 되네요.

 이것으로 cocos2d-x iOS iAD 연동은 마무리 되었습니다. 밑에 내용은 위에서 작업한 코딩 옵션에 따른 iAD 적용 비교 스샷입니다.


ContentSizeIdentifiers가 ADBannerContentSizeIdentifierLandscape 일 때
ADBannerView* adView = [[ADBannerView alloc] initWithFrame:CGRectZero];

 adView 자체 사이즈와 실제 광고 내용 모두 정상적으로 나옵니다.

ADBannerView* adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, 0, 480, 32)];

 가로 480이니 당연히 정상입니다.


 이제 App은 Landscape인데 iAD의 ContentSizeIdentifiers가 ADBannerContentSizeIdentifierPortrait 일 때
ADBannerView* adView = [[ADBannerView alloc] initWithFrame:CGRectZero];

 왼쪽 위에 크기는 가로는 반보다 조금 크게해서 생성되었습니다.

ADBannerView* adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, 0, 480, 32)];

 iAD View의 Frame자체는 가로길이가 화면 사이즈와 같게 480으로 생성되었지만 광고자체 내용인 View는 Frame의 높이는 32인데 ADBannerContentSizeIdentifierPortrait여서 세로모드 처럼 나와 짤려서 나옵니다.

 이것으로 보아 ADBannerView를 initWithFrame할 때 정해주는 사이즈는 iAD View의 외곽 Frame통 사이즈를 위한 것 같습니다. 그리고 일일이 사이즈 정할 필요없이 그냥 CGRectZero로 하면 ContentSizeIdentifiers에 따라 Device 회전 상태에 맞게 알아서 되는 것 같습니다.

 간단하게 샘플정도로 정리해봤습니다. 조금더 보완해줘야 한다면, iAD를 App이 실행되는 동안 계속 출력하지는 않을 것이므로 open, close 기능을 만들어 상황에 따라 표출해줘야 하겠죠. 또한 게임이 아니고 일반 App인 경우 때에따라 화면이 회전이 된다면 그에대한 예외처리도 해줘야 할 듯하구요.
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
- (void)bannerViewActionDidFinish:(ADBannerView *)banner
 이 2가지도 처리해주면 좋겠네요.

댓글

이 블로그의 인기 게시물

'xxx.exe' 프로그램을 시작할 수 없습니다. 지정된 파일을 찾을 수 없습니다.

goorm IDE에서 node.js 프로젝트로 Hello World Simple Server 만들어 띄워보기

애드센스 수익을 웨스턴 유니온으로 수표대신 현금으로 지급 받아보자.