考慮到以下兩點:
1. Cocos2d-x從3.7版開始優化對Android Studio的支援,相信這一趨勢還會繼續。可惜目前相關幫助文檔還不完善,很多東西需要自己摸索。
2. 廣點通廣告平台的官方幫助文檔沒有針對Cocos2d-x。
是以在此對自己所學所得做一些總結,也希望能幫助到那些處在摸索之中的朋友們。
本文所用cocos2d-x為3.8版,android studio為1.3.2版,廣點通SDK為4.8版。(插播廣告:如需添加IOS版廣告平台請戳這裡)
準備工作:
1)進入廣點通官網,新增賬號。注冊時需要上傳身份證正反面照片(好像還需要手持身份證照片)以及銀行賬戶。然後等待稽核。廣點通稽核時間略長,大概要一個禮拜。
2)稽核通過後就可以建立應用和廣告位。
3)下載下傳廣點通安卓版SDK。廣點通的SDK檔案夾裡有示例代碼,可以打開看一看,官網上也幫助文檔,但是沒有針對Cocos2d-x的。
開幹正事:
1)在搞懂如何添加之前,建議不要直接在自己的工程裡添加,最好建立一個HelloWorld項目用于試驗。關于如何建立一個Android Studio版的HelloWorld項目,請參考部落客另一篇博文。
2)打開下載下傳下來的廣點通檔案夾,複制其中的GDTUnionSDK.4.8.509.jar檔案,并拷貝到建立的HelloWorld項目下proj.android-studio->app->libs->armeabi檔案夾中(該檔案夾隻有在第一步中完成編譯之後才會出現)。并在Android Studio中打開HelloWorld項目,找到GDTUnionSDK.4.8.509.jar(在jiniLibs->armeabi下面),右擊,選擇Add As Library。這樣就把廣點通SDK添加到我們的項目中了。
3)在Android Studio中打開AndroidManifest.xml檔案,往裡面添加廣點通權限聲明和Activity聲明。添加完後完整代碼如下所示:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.istudy.HelloWorldGDT"
android:installLocation="auto">
<!--廣點通聲明1開始-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_UPDATES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--廣點通聲明1結束-->
<uses-feature android:glEsVersion="0x00020000" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher">
<!-- Tell Cocos2dxActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="cocos2dcpp" />
<!--廣點通聲明2開始-->
<service
android:name="com.qq.e.comm.DownloadService"
android:exported="false" >
</service>
<activity
android:name="com.qq.e.ads.ADActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize" >
</activity>
<!--廣點通聲明2結束-->
<activity
android:name="org.cocos2dx.cpp.AppActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
4)在Android Studio裡打開AppActivity,往裡面添加顯示廣告的Java代碼。但是由于我們Cocos2d-x的場景都是用C++實作的,是以我們在這裡需要利用Handler來做接口。這和官方幫助文檔不同。添加完後完整代碼如下所示:
AppActivity
package org.cocos2dx.cpp;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import com.qq.e.ads.banner.ADSize;
import com.qq.e.ads.banner.AbstractBannerADListener;
import com.qq.e.ads.banner.BannerView;
public class AppActivity extends Cocos2dxActivity {
//聲明應用ID
public static final String APPID = "1101152570";
//聲明廣告條容器,廣告條和廣告位ID
private static RelativeLayout bannerContainer;
BannerView bv;
public static final String BannerPosID="9079537218417626401";
//聲明handler用于發送消息
private static Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//建立廣告條容器
bannerContainer = new RelativeLayout(this);
RelativeLayout.LayoutParams parentLayoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
this.addContentView(bannerContainer, parentLayoutParams);
//加載或解除安裝廣告
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:// showBannerAd()
if (bannerContainer.getChildCount() == 0) {
//初始化并加載廣告條
initBanner();
bv.loadAD();
}else{
if (bv != null) {
bv.setVisibility(View.VISIBLE);
bv.loadAD();
}
}
break;
case 1: //hideBannerAd()
if (bv != null) {
doCloseBanner();
}
break;
default:
break;
}
}
};
}
private void initBanner() {
bv = new BannerView(this, ADSize.BANNER, APPID, BannerPosID);
bv.setRefresh(30);
bv.setShowClose(true);//一定要有這個關閉按鈕,否則某些應用商店不給通過,雖然官方示例代碼中沒有。本人就被坑過一次。
bv.setADListener(new AbstractBannerADListener() {
@Override
public void onNoAD(int arg0) {
Log.i("AD_DEMO", "BannerNoAD,eCode=" + arg0);
}
@Override
public void onADReceiv() {
Log.i("AD_DEMO", "ONBannerReceive");
}
});
//添加廣告并設定它的位置
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
//layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
bannerContainer.addView(AppActivity.this.bv, layoutParams);
}
//重新整理
private void doRefreshBanner() {
if (bv == null) {
initBanner();
}
bv.loadAD();
}
//關閉
private void doCloseBanner() {
bannerContainer.removeAllViews();
bv.destroy();
bv = null;
}
//打開和關閉廣告接口
public static void showBannerAd() {
handler.sendEmptyMessage(0);
}
public static void hideBannerAd() {
handler.sendEmptyMessage(1);
}
}
注意我們這裡是用代碼來建立一個RelativeLayer布局對象來作為廣告條容器的,而非通過布局檔案xml來實作的,這一點和官方文檔也不同。
5)在Cocos2d-x的Classes下面建立一個類,命名為GDTAD,在裡面通過jni把Java的廣告開關轉換成了C++函數,以便在Cocos2d-x場景裡調用。完整代碼如下:
GDTAD.h
#ifndef CLASSES_GDTAD_H
#define CLASSES_GDTAD_H
class GDTAD {
public:
static void showBannerAd();
static void hideBannerAd();
};
#endif //CLASSES_GDTAD_H
GDTAD.cpp
#include "GDTAD.h"
#include "cocos2d.h"
USING_NS_CC;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/jni/JniHelper.h"
#include <jni.h>
const char* AppActivityCalssName = "org/cocos2dx/cpp/AppActivity";
//顯示廣告條
void GDTAD::showBannerAd()
{
cocos2d::JniMethodInfo showBanner;
if (cocos2d::JniHelper::getStaticMethodInfo(showBanner, AppActivityCalssName, "showBannerAd", "()V")) {
showBanner.env->CallStaticVoidMethod(showBanner.classID, showBanner.methodID);
}
else{
log("jni:showBannerStatic false");
}
}
//隐藏廣告條
void GDTAD::hideBannerAd()
{
cocos2d::JniMethodInfo hideBanner;
if (cocos2d::JniHelper::getStaticMethodInfo(hideBanner, AppActivityCalssName, "hideBannerAd", "()V")) {
hideBanner.env->CallStaticVoidMethod(hideBanner.classID, hideBanner.methodID);
}
else{
log("jni:hideBannerStatic false");
}
}
#else
//廣告條
void GDTAD::showBannerAd()
{
log("showBannerAd() called");
return;
}
void GDTAD::hideBannerAd()
{
log("hideBannerAd() called");
return;
}
#endif
6)接下來就可以愉快的在Cocos2d-x場景裡添加廣告了。這裡我們在HelloWorld場景的最上端添加一個廣告條,完整代碼如下
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "GDTAD.h"
class HelloWorld : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#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;
}
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.
// add a "close" icon to exit the progress. it's an autorelease object
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));
// create menu, it's an autorelease object
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);
/
// 3. add your codes below...
//添加廣告條
GDTAD::showBannerAd();
// 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::menuCloseCallback(Ref* pSender)
{
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
7)編譯并運作。在編譯之前需要在Android.mk檔案裡面添加GDTAD.cpp的路徑,否則建立的C++檔案無法被編譯進來。比如我這裡可以輸入vi ~/Documents/HelloWorld/proj.android-studio/app/jni/Android.mk進行添加。最終運作後效果如下圖所示:

從效果圖中可以看出我們已經在AndroidManifest.xml裡把橫屏改成了豎屏。(這個圖檔沒有更新,更新後廣告條左上角會有一個叉叉,用來關閉廣告)。
水準有限,如有不妥,歡迎指正!
參考文獻:
[1]廣點通官方示例代碼。
[2]http://blog.csdn.net/u014078216/article/details/48931565