之前写了篇Cocos2d-x 3.X, iOS版添加广点通广告。但是那篇只提到了广告条的集成(有需要的,请戳这里)。不少网友反映出对插屏广告的需求。所以在这里就把插屏广告的集成也写一遍。其实方法是一样的,就是做一个C++类,把它的源文件后缀改成mm,这样就可以把广点通的Objective C指令放里面和C++一起混编。同时它的头文件不含Objective C指令,这样就可以被纯C++文件包含。
本文所用Cocos2d-x为3.9版,Xcode为7.1版,广点通SDK为IOS 4.1版。(插播广告:如需添加安卓版广告请戳这里)
准备工作:
1)进入广点通官网,注册账号。注册时需要上传身份证正反面照片(好像还需要手持身份证照片)以及银行账户。然后等待审核。广点通审核时间略长,大概要一个礼拜。
2)审核通过后就可以创建应用和广告位,并得到应用和广告位ID。这两个ID会被添加到我们的程序当中。
3)下载广点通IOS版SDK。广点通的SDK文件夹里有示例代码和帮助文档Guide 4.1.pdf。可以打开看一看(可以结合本文一起阅读),但是没有针对Cocos2d-x的。
开干正事:
1)新建HelloWorld项目。在搞懂如何添加之前,建议不要直接在自己的工程里面添加,最好新建一个HelloWorld项目用于试验。新建IOS版的HelloWorld项目相对简单。配置好环境变量后,只需一行命令即可完成。这个可以参考Cocos2d-x官方文档。
2)添加广点通SDK。打开下载好的广点通SDK文件夹,将其中libs里面的所有文件都拖入Xcode的HelloWorld项目中(注意libGDTMobSDK.a得放在项目根目录下,如果放在Classes下面链接时会找不到)。
3)添加相应Frameworks。进入Xcode项目的TARGETS部分,选择HelloWorld-mobile,进入Build Phases下的Link Binary With Libraries。往里面添加以下Frameworks:
AdSupport.framework,CoreLocation.framework,QuartzCore.framework (注意官方文档上单词拼写错误,漏了一个t),SystemConfiguration.framework,CoreTelephony.framework,libz.dylib或 libz.tbd,Security.framework,StoreKit.framework
这些都是广点通帮助文档里要求添加的Frameworks。但是这些还不够,还需要往里面添加两个frameworks:GameController.framework和MediaPlayer.framework。具体原因请参考之前的那篇广告条添加(戳这里)。
4)更改导入静态库设置。再次进入Xcode项目的TARGETS部分,选择HelloWorld-mobile, 进入Build Settings下面的Linking部分,往Other Linker Flags里添加两个参数-ObjC和-lstdc++。
以上部分和官方帮助文档Guide 4.1.pdf一致,如有不清楚的地方可以参考官方文档。接下来就不太一样了,请留意。
5)找到RootViewController.h, 令RootViewController继承一个广点通广告条相关协议,以便让RootViewController成为广告的代理。并且为了在测试时监控广告是否加载成功,我们在RootViewController.mm里实现两个协议方法。完整代码如下所示:
RootViewController.h
#import
#import "GDTMobInterstitial.h"
@interface RootViewController : UIViewController {
}
- (BOOL) prefersStatusBarHidden;
@end
#import "RootViewController.h"
#import "cocos2d.h"
#import "platform/ios/CCEAGLView-ios.h"
static NSString *INTERSTITIAL_STATE_TEXT = @"插屏状态";
@implementation RootViewController
/**
* 广告预加载成功回调
* 详解:当接收服务器返回的广告数据成功后调用该函数
*/
- (void)interstitialSuccessToLoadAd:(GDTMobInterstitial *)interstitial
{
NSLog(@"%@:%@",INTERSTITIAL_STATE_TEXT,@"Success Loaded.");
}
/**
* 广告预加载失败回调
* 详解:当接收服务器返回的广告数据失败后调用该函数
*/
- (void)interstitialFailToLoadAd:(GDTMobInterstitial *)interstitial error:(NSError *)error
{
NSLog(@"%@:%@",INTERSTITIAL_STATE_TEXT,@"Fail Loaded." );
}
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
// Override to allow orientations other than the default portrait orientation.
// This method is deprecated on ios6
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsLandscape( interfaceOrientation );
}
// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead
- (NSUInteger) supportedInterfaceOrientations{
#ifdef __IPHONE_6_0
return UIInterfaceOrientationMaskAllButUpsideDown;
#endif
}
- (BOOL) shouldAutorotate {
return YES;
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
auto glview = cocos2d::Director::getInstance()->getOpenGLView();
if (glview)
{
CCEAGLView *eaglview = (CCEAGLView*) glview->getEAGLView();
if (eaglview)
{
CGSize s = CGSizeMake([eaglview getWidth], [eaglview getHeight]);
cocos2d::Application::getInstance()->applicationScreenSizeChanged((int) s.width, (int) s.height);
}
}
}
//fix not hide status on ios7
- (BOOL)prefersStatusBarHidden
{
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
#ifndef AdInterC_hpp
#define AdInterC_hpp
//要被cpp包含,所以不能有任何Objective C指令, 也就是说这里即不能#import GDTMobBannerView.h,
//也不能用@class GDTMobBannerView. 只能通过一个结构体来间接的调用GDTMobBannerView
struct AdInterImpl;
class AdInterC
{
public:
AdInterC();
~AdInterC();
void loadAd();//加载广告
void showAd();//显示广告
private:
AdInterImpl* impl;
};
#endif /* AdInterC_hpp */
#include "AdInterC.h"
#include "RootViewController.h"
struct AdInterImpl
{
GDTMobInterstitial * _interObj;
};
AdInterC::AdInterC()
{
impl = new AdInterImpl();
}
AdInterC::~AdInterC()
{
impl->_interObj.delegate=nil;
delete impl;
}
void AdInterC::loadAd()
{
impl->_interObj = [[GDTMobInterstitial alloc] initWithAppkey:@"2211675583" placementId:@"2954362461573316031"];//注意测试的时候就要改成自己申请来的ID,否则很难加载成功
auto rootViewController = (RootViewController*) [[[UIApplication sharedApplication] keyWindow] rootViewController];
impl->_interObj.delegate = rootViewController; //设置委托
impl->_interObj.isGpsOn = NO; //【可选】设置GPS开关 //预加载广告
[impl->_interObj loadAd];
}
void AdInterC::showAd()
{
UIViewController *vc = [[[UIApplication sharedApplication] keyWindow]
rootViewController];
[impl->_interObj presentFromRootViewController:vc];
}
注意要把app key和placement id改成自己申请来的,否则很难加载成功。另外要把加载方法和显示方法分开。
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "AdInterC.h"
class HelloWorld : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
//加载回调
void loadCallback(cocos2d::Ref* pSender);
//显示回调
void showCallback(cocos2d::Ref* pSender);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
AdInterC *ad;
};
#endif // __HELLOWORLD_SCENE_H__
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//
// 1. super init first
if ( !Layer::init() )
{
return false;
}
//创建一个广告类对象
ad=new AdInterC();
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
/
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it.
//加载菜单项
auto loadItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::loadCallback, this));
//显示菜单项
auto showItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::showCallback, this));
loadItem->setPosition(Vec2(origin.x + loadItem->getContentSize().width/2 ,
origin.y + loadItem->getContentSize().height/2));
showItem->setPosition(Vec2(origin.x + visibleSize.width - showItem->getContentSize().width/2 ,
origin.y + showItem->getContentSize().height/2));
// create menu, it's an autorelease object
auto menu = Menu::create(loadItem, showItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);
/
// 3. add your codes below...
// add a label shows "Hello World"
// create and initialize a label
auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));
// add the label as a child to this layer
this->addChild(label, 1);
// add "HelloWorld" splash screen"
auto sprite = Sprite::create("HelloWorld.png");
// position the sprite on the center of the screen
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
// add the sprite as a child to this layer
this->addChild(sprite, 0);
return true;
}
void HelloWorld::loadCallback(Ref* pSender)
{
ad->loadAd();
}
void HelloWorld::showCallback(Ref* pSender)
{
ad->showAd();
}
水平有限,如有不妥,欢迎指正!
参考资料:
1)广点通官方文档Guide 4.0.pdf
2) 广大网友