先上成功图
image.png
下面开始讲我历时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
image.png
注意这里的sdk一般是官方最新的
一开始我下载的时候是5.4.2 过了一段时间又下载到了5.4.3
然后接sdk突然卡住了2个月(期间经历公司破产换工作,新工作压力的时间,最近从新开始研究)下载了 5.6.0
image.png
最终我使用了5.6.0
另外我也没有接入ios 我只接入了android的 如果有需要的朋友可以自行研究
下载过后解压放入自己的MyGame项目目录
我的目录结构
我的目录结构2
接着来填写Android.mk
官方给出的示例是这样的
image.png
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
这里被坑了很久
与官方教程不同的是
image.png
填完后as里面编译
image.png
或者
image.png
同官方教程
image.png
接下来是官方教程的第3步
image.png
打开这个链接
首先重要的是
image.png
请按要求准备前提条件
继续
image.png
image.png
image.png
添加项目这里由于我已经注册过了 写教程的时候就没了这个过程 可能需要你自己去尝试
继续往下看教程
image.png
image.png
这里的设置是指的刚刚的filebase控制台设置
image.png
点击这里下载这个重要的链接文件
点击这里下载这个重要的链接文件
image.png
image.png
这是我的目录结构
image.png
image.png
请真机运行你这个时候的项目 确保能够看到cocos的 hello world 界面而没有报错
这个时候添加sdk
根级 build.gradle
image.png
这是我的版本
image.png
classpath 'com.google.gms:google-services:4.0.1'
模块 Gradle 文件(通常是 app/build.gradle)
image.png
这是我的版本
image.png
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'
接下来看教程
image.png
这些都是最新的库版本 但是得对应最新的官方sdk包 就是上面说的sdk版本5.6.0(也许你接的时候并不是5.6.0)
image.png
接下来 我们回到主教程
https://firebase.google.com/docs/admob/cpp/cocos2d-x?hl=zh-cn
再次真机运行app看有没有报错
再次真机运行app看有没有报错
没有报错 继续
这里需要注册一下admob的 尽量与google filebase 账号关联
https://apps.admob.com/
image.png
注册完了以后 这里会有2个ID
这个是广告单元的ID 简称 [广告ID]
image.png
这里是Firebase 应用ID 简称 [应用ID]
image.png
然后有了这2个ID 继续我们刚才的主教程
image.png
头文件包含
image.png
我的
#include "../firebase_cpp_sdk/include/firebase/admob/types.h"
接着按照教程做 到
image.png
我的头文件 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 <android/log.h>
#include <jni.h>
#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效果
image.png
重要1
image.png
重要2
image.png
到这里 基本就运行完毕了
如果中间有错误 请查看as logcat 尽量先看error
如果出现
Ad failed to load : 0
有2种情况 一种是你刚刚发布admob账号下的广告应用 可能需要等几小时 或者几天
具体以关联admob的 邮箱收件为准
如果收到了这一条消息 证明你已经通过了这一条
image.png
还有一种情况就是我遇到的情况 就是我错把广告ID 填成了应用ID导致 广告显示部分完全是黑色的
这里注意我上面反复强调的应用ID就行
重要链接:
https://firebase.google.com/docs/admob/android/quick-start
还有一处重要位置我也有更改
image.png
注意这里是应用ID
<application
...cocos other code
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX"/>
</application>
image.png
!!! 还有一个非常重要的设置
就是刚刚的admob的控制台
https://apps.admob.com/
image.png
一定要设置付款信息 否则也是会导致广告无法正常播放的
到这里基本就已经成功了
如果还没有成功 建议google搜索 一定比百度有用
搜索结果尽量先看https://stackoverflow.com/
这里给出的建议 我的问题基本都是这样解决的
另外百度基本解决不了这个SDK的问题
加油 我相信你也可以!!!
另外宣传一下我的独立游戏开发QQ群:386239391
欢迎讨论

image.png












网友评论