先上成功图
下面开始讲我历时5个月(断断续续利用业余时间) 头铁硬刚、不服周(湖北话)的结果
虽然接sdk对别人可能是一个很简单的事情, 但是之前项目一直是做框架和逻辑sdk都交给别人了
所以自己接还是费了许多力气的
如果要接这个sdk 请耐心看完这篇教程 可能到处都是坑 如果不仔细看 你可能会花更多时间采坑
当然也许有些坑我也没有踩过:)
首先admob 是基于filebase的
cocos的环境安装我就不教了 因为这里主要是讲admob 所以环境安装请自行百度
我目前机器里面的环境有
android studio 3.2.1
sdk(android studio 自带)
ndk(sdk 里面的子目录 我的是F:\android_sdk\sdk\ndk-bundle) ndk-r14d以上
java 以及设置JAVA_HOME 和 path
创建项目调用cocos 命令行
cocos new MyGame -l cpp
但是我们使用的是android studio 并不是cocos的命令行打包
为什么 因为3.17 以后命令行打包方式已经被cocos 官方放弃了
所以我建议从3.16版本就开始熟悉使用android studio 熟悉打包
下面所有的android studio 简称[as]
首先你需要用as 成功打包一个 cocos2d-x 3.16 的 cpp hello world 项目 能够成功在真机上运行
然后
先阅读链接1
https://firebase.google.com/docs/admob/cpp/cocos2d-x?hl=zh-cn
按照链接1里面的要求先下载sdk
注意这里的sdk一般是官方最新的
一开始我下载的时候是5.4.2 过了一段时间又下载到了5.4.3
然后接sdk突然卡住了2个月(期间经历公司破产换工作,新工作压力的时间,最近从新开始研究)下载了 5.6.0
最终我使用了5.6.0
另外我也没有接入ios 我只接入了android的 如果有需要的朋友可以自行研究
下载过后解压放入自己的MyGame项目目录
接着来填写Android.mk
官方给出的示例是这样的
LOCAL_PATH := $(call my-dir)
# The path to the Firebase C++ SDK, in the project's root directory.
FIREBASE_CPP_SDK_DIR := ../../../firebase_cpp_sdk
APP_ABI := armeabi-v7a x86
STL := $(firstword $(subst _, ,$(APP_STL)))
FIREBASE_LIBRARY_PATH := $(FIREBASE_CPP_SDK_DIR)/libs/android/$(TARGET_ARCH_ABI)/$(STL)
include $(CLEAR_VARS)
LOCAL_MODULE := firebase_app
LOCAL_SRC_FILES := $(FIREBASE_LIBRARY_PATH)/libfirebase_app.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(FIREBASE_CPP_SDK_DIR)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := firebase_feature
LOCAL_SRC_FILES := $(FIREBASE_LIBRARY_PATH)/libfirebase_admob.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(FIREBASE_CPP_SDK_DIR)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/cocos)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/cocos/audio/include)
LOCAL_MODULE := MyGame_shared
LOCAL_MODULE_FILENAME := libMyGame
LOCAL_SRC_FILES := $(LOCAL_PATH)/hellocpp/main.cpp \
$(LOCAL_PATH)/../../../Classes/AppDelegate.cpp \
$(LOCAL_PATH)/../../../Classes/HelloWorldScene.cpp \
$(LOCAL_PATH)/../../../Classes/FirebaseHelper.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../Classes
# _COCOS_HEADER_ANDROID_BEGIN
# _COCOS_HEADER_ANDROID_END
LOCAL_STATIC_LIBRARIES := cocos2dx_static
LOCAL_STATIC_LIBRARIES += firebase_app
LOCAL_STATIC_LIBRARIES += firebase_feature
# _COCOS_LIB_ANDROID_BEGIN
# _COCOS_LIB_ANDROID_END
include $(BUILD_SHARED_LIBRARY)
$(call import-module,.)
# _COCOS_LIB_IMPORT_ANDROID_BEGIN
# _COCOS_LIB_IMPORT_ANDROID_END
这里被坑了很久
与官方教程不同的是
填完后as里面编译
或者
同官方教程
接下来是官方教程的第3步
打开这个链接
首先重要的是
请按要求准备前提条件
继续
添加项目这里由于我已经注册过了 写教程的时候就没了这个过程 可能需要你自己去尝试
继续往下看教程
这里的设置是指的刚刚的filebase控制台设置
点击这里下载这个重要的链接文件
这是我的目录结构
请真机运行你这个时候的项目 确保能够看到cocos的 hello world 界面而没有报错
这个时候添加sdk
根级 build.gradle
这是我的版本
classpath 'com.google.gms:google-services:4.0.1'
模块 Gradle 文件(通常是 app/build.gradle)
这是我的版本
implementation 'com.google.firebase:firebase-core:16.0.7'
implementation 'com.google.firebase:firebase-ads:17.1.3'
implementation 'com.google.firebase:firebase-common:16.1.0'
接下来看教程
这些都是最新的库版本 但是得对应最新的官方sdk包 就是上面说的sdk版本5.6.0(也许你接的时候并不是5.6.0)
接下来 我们回到主教程
https://firebase.google.com/docs/admob/cpp/cocos2d-x?hl=zh-cn
再次真机运行app看有没有报错
没有报错 继续
这里需要注册一下admob的 尽量与google filebase 账号关联
https://apps.admob.com/
注册完了以后 这里会有2个ID
这个是广告单元的ID 简称 [广告ID]
这里是Firebase 应用ID 简称 [应用ID]
然后有了这2个ID 继续我们刚才的主教程
头文件包含
我的
#include "../firebase_cpp_sdk/include/firebase/admob/types.h"
接着按照教程做 到
我的头文件 HelloWorldScene.h 请看中文注释 有细节
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
//这里是我的目录 你可以参考
#include "../firebase_cpp_sdk/include/firebase/admob.h"
#include "../firebase_cpp_sdk/include/firebase/admob/types.h"
#include "../firebase_cpp_sdk/include/firebase/app.h"
#include "../firebase_cpp_sdk/include/firebase/future.h"
#include "../firebase_cpp_sdk/include/firebase/admob/banner_view.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include
#include
#include "platform/android/jni/JniHelper.h"
#endif
class HelloWorld : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
void update(float delta);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
//这里添加一个成员变量
// Create and initialize banner view.
firebase::admob::BannerView* banner_view;
};
#endif // __HELLOWORLD_SCENE_H__
这是我的HelloWorldScene.cpp 请看中文注释 有细节
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
#include "FirebaseHelper.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
return HelloWorld::create();
}
// Print useful error message instead of segfaulting when files are not there.
static void problemLoading(const char* filename)
{
printf("Error while loading: %s\n", filename);
printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HelloWorldScene.cpp\n");
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Scene::init() )
{
return false;
}
auto 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));
if (closeItem == nullptr ||
closeItem->getContentSize().width <= 0 ||
closeItem->getContentSize().height <= 0)
{
problemLoading("'CloseNormal.png' and 'CloseSelected.png'");
}
else
{
float x = origin.x + visibleSize.width - closeItem->getContentSize().width/2;
float y = origin.y + closeItem->getContentSize().height/2;
closeItem->setPosition(Vec2(x,y));
}
// 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...
// add a label shows "Hello World"
// create and initialize a label
auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
if (label == nullptr)
{
problemLoading("'fonts/Marker Felt.ttf'");
}
else
{
// 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");
if (sprite == nullptr)
{
problemLoading("'HelloWorld.png'");
}
else
{
// 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);
}
//sdk从这里开始
#if defined(__ANDROID__)
//这个测试广告ID来自 https://developers.google.com/admob/android/test-ads#enable_test_devices 请仔细阅读
//建议一开始使用这个ID来测试 先能够正常显示后 再进行下面的进一步的正式广告ID测试
//const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111";
// !!!重要 这里是斜杠的广告ID
// Android ad unit IDs.
const char* kBannerAdUnit = "ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX";
#else
// iOS ad unit IDs.
const char* kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716";
#endif
banner_view = new firebase::admob::BannerView();
firebase::admob::AdSize ad_size;
ad_size.ad_size_type = firebase::admob::kAdSizeStandard;
ad_size.width = 320;
ad_size.height = 50;
banner_view->Initialize(getAdParent(), kBannerAdUnit, ad_size);
// Schedule updates so that the Cocos2d-x update() method gets called.
this->scheduleUpdate();
return true;
}
void HelloWorld::update(float delta) {
// Check that the banner has been initialized.
if (banner_view->InitializeLastResult().status() ==
firebase::kFutureStatusComplete) {
// Check that the banner hasn't started loading.
if (banner_view->LoadAdLastResult().status() ==
firebase::kFutureStatusInvalid) {
// Make the banner visible and load an ad.
CCLOG("Loading a banner.");
banner_view->Show();
//官方只有这一句
firebase::admob::AdRequest my_ad_request = {};
// ad_request 属性设置 AAA ------------------
// 这里的段落来自上面测试ID的那个网站
// 这里请自行翻译英文 我采用的官方默认值
// If the app is aware of the user's gender, it can be added to the
// targeting information. Otherwise, "unknown" should be used.
my_ad_request.gender = firebase::admob::kGenderUnknown;
// 这里请自行翻译英文 我采用的官方默认值
// The user's birthday, if known. Note that months are indexed from one.
my_ad_request.birthday_day = 10;
my_ad_request.birthday_month = 11;
my_ad_request.birthday_year = 1976;
// 这里请自行翻译英文 我采用的官方默认值
// Additional keywords to be used in targeting.
static const char* kKeywords[] = {"AdMob", "C++", "Fun"};
my_ad_request.keyword_count = sizeof(kKeywords) / sizeof(kKeywords[0]);
my_ad_request.keywords = kKeywords;
// 这里请自行翻译英文 我采用的官方默认值
// "Extra" key value pairs can be added to the request as well.
static const firebase::admob::KeyValuePair kRequestExtras[] = {
{"the_name_of_an_extra", "the_value_for_that_extra"}};
my_ad_request.extras_count = sizeof(kRequestExtras) / sizeof(kRequestExtras[0]);
my_ad_request.extras = kRequestExtras;
//!!!重要 这里是你的测试设备队列 请参考上面测试ID网站说明
// 如果不添加这个 要么你的真机测试流程无法跑起来 要么你点击广告会被别人举报(无效点击) 可能导致被封号 慎重
// 另外我测试这些机器 有3台安装了360手机助手的 谷歌安装器 并且安装了相关的谷歌套件 有2台什么也没有安 但是都可以运行成功
// 请关注 as logcat 的 AdRequest.Builder.addTestDevice 得到你的测试设备ID填入下面队列
// Register the device IDs associated with any devices that will be used to
// test your app. Below are sample test device IDs used for making the ad request.
static const char* kTestDeviceIDs[] =
{"B22C21BE0A5510577E3141D66C34B72B",//测试机1
"28399F3437D1FA3CA8F8C4BC150A4CEA",//测试机2
"89B5AD7495729AE69BFA72D5477C66BA",//测试机3
"BFCF6E25A5308D10E4F798C40D261CE2",//测试机4
"B621B231ECA4C84418EE7FDA1073CAE5"};//测试机5
my_ad_request.test_device_id_count =
sizeof(kTestDeviceIDs) / sizeof(kTestDeviceIDs[0]);
my_ad_request.test_device_ids = kTestDeviceIDs;
// ad_request 属性设置 AAA ------------------
//官方的第二句
banner_view->LoadAd(my_ad_request);
}
}
}
void HelloWorld::menuCloseCallback(Ref* pSender)
{
//Close the cocos2d-x game scene and quit the application
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
/*To navigate back to native iOS screen(if present) without quitting the application ,do not use Director::getInstance()->end() and exit(0) as given above,instead trigger a custom event created in RootViewController.mm as below*/
//EventCustom customEndEvent("game_scene_close_event");
//_eventDispatcher->dispatchEvent(&customEndEvent);
}
关于测试admob 重要 请仔细阅读
https://developers.google.com/admob/android/test-ads#enable_test_devices
这是我使用的测试ID效果
重要1
重要2
到这里 基本就运行完毕了
如果中间有错误 请查看as logcat 尽量先看error
如果出现
Ad failed to load : 0
有2种情况 一种是你刚刚发布admob账号下的广告应用 可能需要等几小时 或者几天
具体以关联admob的 邮箱收件为准
如果收到了这一条消息 证明你已经通过了这一条
还有一种情况就是我遇到的情况 就是我错把广告ID 填成了应用ID导致 广告显示部分完全是黑色的
这里注意我上面反复强调的应用ID就行
重要链接:
https://firebase.google.com/docs/admob/android/quick-start
还有一处重要位置我也有更改
image.png
注意这里是应用ID
!!! 还有一个非常重要的设置
就是刚刚的admob的控制台
https://apps.admob.com/
一定要设置付款信息 否则也是会导致广告无法正常播放的
到这里基本就已经成功了
如果还没有成功 建议google搜索 一定比百度有用
搜索结果尽量先看https://stackoverflow.com/
这里给出的建议 我的问题基本都是这样解决的
另外百度基本解决不了这个SDK的问题
加油 我相信你也可以!!!
另外宣传一下我的独立游戏开发QQ群:386239391
欢迎讨论