本指南将演示如何将结合了 Firebase 的 AdMob 添加到新建的 Cocos2d-x 项目中。如果您还没有项目,则应先满足前提条件,然后再通过命令行新建一个 cocos 项目:
cocos new MyGame -l cpp
注意
:AdMob 仅支持针对 Android 和 iOS 构建的 Cocos2d-x 应用,不支持桌面应用。本指南假定您只开发适用于 Android/iOS 的 Cocos 应用,但您可以使用以下 #if
指令封装完整的 AdMob 集成,以确保其仅在移动应用环境中执行:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS) ...#endif
前提条件
您的设备上必须安装以下工具:
- 最新版本的 Cocos2d-x
- Python 2.7 或更高版本
- NDK r10d 或更高版本(仅 Android 开发需要)
- CocoaPods 1.0.0 或更高版本(仅 iOS 开发需要)
获取 AdMob 和 Firebase C++ SDK
下载 Firebase C++ SDK。将文件解压缩到 Cocos2d-x 项目的顶级目录中,此目录包含您的 proj.android-studio
目录和 proj.ios_mac
目录。将文件夹命名为 firebase_cpp_sdk
。
设置 iOS
以下步骤说明了如何将 Firebase SDK 导入到新建的 Cocos2d-x iOS 项目中。
按照相应步骤将 Firebase 添加至您的应用。完成之后,proj.ios_mac/
目录中的 Xcode 项目应该会引用 GoogleService-Info.plist
文件。
在您的 proj.ios_mac/
目录中创建一个 Podfile,其中包含以下内容:
source 'https://github.com/CocoaPods/Specs.git'platform :ios, '7.0'# Replace "MyGame" with the name of your game.target 'MyGame-mobile' do pod 'Firebase' pod 'Firebase/AdMob'end
运行 pod update
以安装 CocoaPods,然后按照 CocoaPods 的说明打开 MyGame.xcworkspace
。此时,您的项目中已包含 Firebase 和 AdMob iOS SDK。
CocoaPods 会发出有关一些属性缺少 $(inherited)
的警告。转到 Xcode 中 MyGame 移动应用目标的构建设置,然后将 $(inherited)
添加到以下每个构建设置的列表底部:
- Other Linker Flags
- Preprocessor Macros
- Library Search Paths
在编译设置中,将 $(PROJECT_DIR)/../firebase_cpp_sdk/frameworks/ios/universal
添加到 Framework Search Paths,将 $(PROJECT_DIR)/../firebase_cpp_sdk/include
添加到 Header Search Paths。
接下来,您需添加对要使用的库的引用。右键点击您的项目,然后选择 Add Files to "MyGame"。在 firebase_cpp_sdk/frameworks/ios/universal
目录中,选择 firebase.framework
和 firebase_admob.framework
。在添加相应框架之前,取消选中 Copy Items if Needed 选项。通过您在上一步中添加的构建设置,Xcode 可了解在哪里找到这些框架。
依次点击 Build Phases > Link Binary with Libraries 以添加 GameController.framework
。
按照 AdMob 的应用传输安全指南来操作,确保所有广告都能在 iOS 9 及更高版本上正常运行。
检查点:您应该能从 Xcode 构建和运行 iOS 应用。
注意
:使用 CocoaPods 会产生负面影响,即您将无法再从命令行中使用 cocos run -p
构建 iOS 应用。
现在,您的 iOS 项目已经与 AdMob 和 Firebase 相集成。 您可以设置 Android 项目了。
设置 Android
以下步骤说明了如何将 Firebase SDK 导入到新建的 Cocos2d-x Android 项目中。
打开 proj.android-studio/app/jni/Android.mk
,然后添加下方以粗体显示的各行内容。确保将 FIREBASE_CPP_SDK_DIR
设置为您刚下载的 Firebase C++ SDK 的本地路径。
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)/libapp.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)/libadmob.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 := hellocpp/main.cpp \
../../../Classes/AppDelegate.cpp \
../../../Classes/HelloWorldScene.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检查您是否仍能编译 Cocos 应用:
cocos compile -p android --ap android-24 --android-studio --app-abi armeabi-v7a
按照相应步骤将 Firebase 添加至您的应用(此应用位于 proj.android-studio/
目录中)。
在您的 app/build.gradle
中添加广告包:
compile 'com.google.firebase:firebase-ads:11.8.0'
检查您是否仍能编译 Cocos 应用:
cocos compile -p android --ap android-42 --android-studio --app-abi armeabi-v7a
您的 Android 项目现在已经引用 Firebase C++ SDK 中的 AdMob 组件。
C++ 集成
现在,您的 iOS 和 Android 项目已在 Firebase C++ SDK 中被引用,接下来便是开始使用 SDK 并加载一些广告。
初始化 Firebase 和 AdMob
建议您在应用生命周期中尽早初始化 Firebase 和 AdMob。要为 Cocos2d-x 项目添加这个初始化代码,最自然的地方是在 AppDelegate.cpp
文件中:
AppDelegate.cpp
#include "firebase/app.h"
#include "firebase/admob.h"
USING_NS_CC
;
bool
AppDelegate
::
applicationDidFinishLaunching
()
{
...
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
// Initialize Firebase for Android.
firebase::App* app = firebase::App::Create(
firebase::AppOptions(), JniHelper::getEnv(), JniHelper::getActivity());
// Initialize AdMob.
firebase::admob::Initialize(*app, "INSERT_YOUR_ADMOB_ANDROID_APP_ID");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
// Initialize Firebase for iOS.
firebase::App* app = firebase::App::Create(firebase::AppOptions());
// Initialize AdMob.
firebase::admob::Initialize(*app, "INSERT_YOUR_ADMOB_IOS_APP_ID");
#endif
// Initialize AdMob.
firebase::admob::Initialize(*app);
// Create a scene. it's an autorelease object.
auto
scene
=
HelloWorldScene
::
createScene
();
// run
director
->
runWithScene
(
scene
);
return
true
;
}
在 Android 上,创建 Firebase 应用需要一个 JNI 环境和 Activity。上面的示例代码使用 Cocos2d-x 中的 JniHelper
类来提供这些参数。
获取广告父级对象
AdMob 需要 firebase::admob::AdParent
对象来初始化每种广告格式。此对象对应于 Android 上的 Activity
和 iOS 上的 UIView
。以下辅助类会创建单个 getAdParent()
方法,该方法可根据平台返回相应对象。
FirebaseHelper.h
#ifndef __FIREBASE_HELPER_H__#define __FIREBASE_HELPER_H__#include "firebase/admob/types.h"#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)#include <jni.h>#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)extern "C" {#include <objc/objc.h>} // extern "C"#endif// Returns a variable that describes the ad parent for the app. On Android// this will be a JObject pointing to the Activity. On iOS, it's an ID pointing// to the root view of the view controller.firebase::admob::AdParent getAdParent();#endif // __FIREBASE_HELPER_H__
FirebaseHelper.cpp
#include "FirebaseHelper.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/jni/JniHelper.h"
#endif
USING_NS_CC;
firebase::admob::AdParent getAdParent() {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
// Returns the iOS RootViewController's main view (i.e. the EAGLView).
return (id)Director::getInstance()->getOpenGLView()->getEAGLView();
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
// Returns the Android Activity.
return JniHelper::getActivity();
#else
// A void* for any other environments.
return 0;
#endif
}
将此 FirebaseHelper 类添加到项目的 Classes/
文件夹中。确保将此文件添加到适用于 iOS 的 Xcode 项目中,并为 Android 更新 Android.mk 中的本地源文件:
LOCAL_SRC_FILES
:=
hellocpp
/
main
.
cpp
\
../../../
Classes
/
AppDelegate
.
cpp
\
../../../
Classes
/
HelloWorldScene
.
cpp
\
../../../Classes/FirebaseHelper.cpp
加载横幅广告
以下示例完整地演示了如何使用上文定义的 getAdParent()
方法加载横幅广告。
#include "FirebaseHelper.h"
#include "firebase/admob.h"
#include "firebase/admob/types.h"
#include "firebase/app.h"
#include "firebase/future.h"
#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
USING_NS_CC;
bool HelloWorld::init()
{
// General scene setup ...
#if defined(__ANDROID__)
// Android ad unit IDs.
const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111";
#else
// iOS ad unit IDs.
const char* kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716";
#endif
// Create and initialize banner view.
firebase::admob::BannerView* banner_view;
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 = {};
banner_view->LoadAd(my_ad_request);
}
}
}
您可以在自己的 C++ 应用中使用 AdMob 来展示广告。本指南将向您介绍如何与 Firebase 集成以及如何与 Google Mobile Ads SDK 互动。
如果这是您首次依据本指南进行操作,我们建议您下载 AdMob 测试应用并利用它进行学习。
与 Firebase 集成
完成针对 iOS 进行设置或针对 Android 进行设置部分中的步骤,将 AdMob 和 Firebase 添加到您的 C++ 应用中。
注意:如果您使用的是 AdMob 测试应用,则下列步骤已经替您完成。您应该现在就可以运行该测试应用。
在您应用的 C++ 代码中包含以下头文件:
#include "firebase/admob.h"#include "firebase/admob/types.h"#include "firebase/app.h"#include "firebase/future.h"
将以下代码添加到您应用的 C++ 代码中,以使用 AdMob 应用 ID 初始化 AdMob 库(这段代码应在创建横幅广告视图或插页式广告之前执行):
#if defined(__ANDROID__)
// Create the Firebase app.
firebase::App* app =
firebase::App::Create(firebase::AppOptions(),
your_jni_env,
your_android_activity);
// Your Android AdMob app ID.
const char* kAdMobAppID = "ca-app-pub-XXXXXXXXXXXXXXXX~NNNNNNNNNN";
#else
// Create the Firebase app.
firebase::App* app =
firebase::App::Create(firebase::AppOptions());
// Your iOS AdMob app ID.
const char* kAdMobAppID = "ca-app-pub-XXXXXXXXXXXXXXXX~NNNNNNNNNN";
#endif // __ANDROID__
// Initialize the AdMob library with your AdMob app ID.
firebase::admob::Initialize(*app, kAdMobAppID);
注意
:AdMob 应用 ID 是移动应用在 AdMob 控制台中注册时获得的唯一标识符。在应用启动时初始化 Google Mobile Ads SDK 可便于 SDK 获取应用级设置,并尽早执行配置任务。这样有助于减少初始广告请求的延迟时间。
与 Google Mobile Ads SDK 互动
设置广告单元 ID
在编写 iOS 和 Android 上都能支持的 C++ 代码时,您可能需要使用预处理器指令来定义只应在某个特定操作系统上编译的代码。要在 iOS 和 Android 上展示横幅广告和插页式广告,我们建议您为每个操作系统和每个唯一的广告展示位置创建一个新的广告单元 ID。我们已针对 iOS 和 Android 操作系统创建了以下广告单元 ID,并将这些 ID 配置为始终投放测试广告:
#if defined(__ANDROID__)// Android ad unit IDsconst char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111";const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/1033173712";#else// iOS ad unit IDsconst char* kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716";const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/4411468910";#endif
设置横幅广告视图
将以下头文件添加到应用的 C++ 代码中:
#include "firebase/admob/banner_view.h"
声明并实例化一个 BannerView
对象:
firebase::admob::BannerView* banner_view;banner_view = new firebase::admob::BannerView();
创建一个 AdSize
并初始化该横幅广告视图:
firebase::admob::AdSize ad_size;
ad_size.ad_size_type = firebase::admob::kAdSizeStandard;
ad_size.width = 320;
ad_size.height = 50;
// my_ad_parent is a reference to an iOS UIView or an Android Activity.
// This is the parent UIView or Activity of the banner view.
banner_view->Initialize(static_cast<firebase::admob::AdParent>(my_ad_parent), kBannerAdUnit, ad_size);
设置插页式广告
将以下头文件添加到应用的 C++ 代码中:
#include "firebase/admob/interstitial_ad.h"
声明并实例化一个 InterstitialAd
对象:
firebase::admob::InterstitialAd* interstitial_ad;
interstitial_ad = new firebase::admob::InterstitialAd();
初始化该插页式广告:
// my_ad_parent is a reference to an iOS UIView or an Android Activity.// This is the parent UIView or Activity of the interstitial ad.interstitial_ad->Initialize(static_cast<firebase::admob::AdParent>(my_ad_parent), kInterstitialAdUnit);
创建 AdMob 广告请求
您可以使用 AdMob 库为广告请求提供自定义定位信息。通过设置一个 AdRequest
结构体的若干成员即可完成上述操作。然后,再将该结构体传递给 BannerView::LoadAd()
或 InterstitialAd::LoadAd()
方法。
如需了解有关如何进行广告定位和自定义广告请求的一般信息,请参阅我们的 iOS 和 Android 定位指南。
以下就是 BannerView
和 InterstitialAd
用来发出广告请求的 AdRequest
结构体:
struct AdRequest {
const char **test_device_ids;
unsigned int test_device_id_count;
const char **keywords;
unsigned int keyword_count;
const KeyValuePair *extras;
unsigned int extras_count;
int birthday_day;
int birthday_month;
int birthday_year;
Gender gender;
ChildDirectedTreatmentState tagged_for_child_directed_treatment;
};
声明并初始化该 AdRequest
结构体:
// Initialize all the AdRequest struct member values to zero.firebase::admob::AdRequest my_ad_request = {};
以下代码设置了 AdRequest
结构体的成员值,以便向广告请求中添加定位信息:
// 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;
// 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[] =
{"2077ef9a63d2b398840261c8221a0c9b",
"098fe087d987c9a878965454a65654d7"};
my_ad_request.test_device_id_count =
sizeof(kTestDeviceIDs) / sizeof(kTestDeviceIDs[0]);
my_ad_request.test_device_ids = kTestDeviceIDs;
将 AdRequest
结构体传递给 BannerView::LoadAd()
和 Interstitial::LoadAd()
方法:
banner_view->LoadAd(my_ad_request);interstitial_ad->LoadAd(my_ad_request);Note: A single `AdRequest` struct can be reused for multiple calls.
使用 Future 来监控方法调用的完成状态
Future 为您提供了一种用来确定您之前 BannerView
或 InterstitialAd
方法调用的完成状态的方法。例如,当调用 InterstitialAd::LoadAd()
方法时,系统会创建并返回一个新的 Future。应用可以通过轮询 Future 的状态来确定广告何时加载完毕。当 Future 变成已完成状态后,在您的应用下一次自然停止时就可以展示插页式广告了。
BannerView
和 InterstitialAd
类中的大多数方法都有一个对应的“last result”(上次结果)方法,应用可以使用这些方法来获取某个给定操作的最新 Future。例如,InterstitialAd::LoadAd()
方法就有一个名为 InterstitialAd::LoadAdLastResult()
的对应方法。该方法会返回一个 Future 对象,此对象可用于检查上次调用 InterstitialAd::LoadAd()
方法后的状态。
类似地,应用可以使用 BannerView::InitializeLastResult()
方法来获取一个 Future 对象,该对象可显示上次调用 BannerView::Initialize()
方法后的状态(以及错误代码,如果有的话)。如果其状态为已完成,并且错误代码是 firebase::admob::kAdMobErrorNone
,那么您就可以通过调用 BannerView::Show()
方法来显示横幅广告视图:
if (banner_view->InitializeLastResult().status() ==
firebase::kFutureStatusComplete &&
banner_view->InitializeLastResult().error() ==
firebase::admob::kAdMobErrorNone) {
banner_view->Show();
}
上次调用 BannerView::Show()
方法后 Future 的状态变成已完成之后,您就可以将一个广告加载到横幅广告视图中:
if (banner_view->ShowLastResult().status() == firebase::kFutureStatusComplete && banner_view->ShowLastResult().error() == firebase::admob::kAdMobErrorNone) { banner_view->LoadAd(my_ad_request);}
对于插页式广告,则可使用 InterstitialAd::InitializeLastResult()
方法来获取一个 Future 对象,该对象可显示上次调用 InterstitialAd::Initialize()
方法后的状态(以及错误代码,如果有的话)。如果其状态为已完成,并且错误代码为 firebase::admob::kAdMobErrorNone
,您就可以加载插页式广告了:
if (interstitial_ad->InitializeLastResult().status() ==
firebase::kFutureStatusComplete &&
interstitial_ad->InitializeLastResult().error() ==
firebase::admob::kAdMobErrorNone) {
interstitial_ad->LoadAd(my_ad_request);
}
上次调用 InterstitialAd::LoadAd()
方法后 Future 的状态变成已完成之后,您就可以在应用下一次自然停止时展示插页式广告了:
if (interstitial_ad->LoadAdLastResult().status() == firebase::kFutureStatusComplete && interstitial_ad->LoadAdLastResult().error() == firebase::admob::kAdMobErrorNone) { interstitial_ad->Show();}
您还可以注册当 Future 变成已完成状态时要调用的回调函数。以下代码段使用了一个函数指针来实现回调:
// Initialize the interstitial ad.
interstitial_ad->Initialize(static_cast<firebase::admob::AdParent>(my_ad_parent), kInterstitialAdUnit);
// Registers the OnCompletion callback. user_data is a pointer that is passed verbatim
// to the callback as a void*. In this example, we pass the interstitial ad object to be
// used in the OnCompletionCallback function.
interstitial_ad->InitializeLastResult().OnCompletion(OnCompletionCallback, interstitial_ad /*user_data*/);
// The OnCompletion callback function.
static void OnCompletionCallback(const firebase::Future<void>& future, void* user_data) {
// Called when the Future is completed for the last call to the InterstitialAd::Initialize()
// method. If the error code is firebase::admob::kAdMobErrorNone, then you're ready to
// load the interstitial ad.
firebase::admob::InterstitialAd *interstitial_ad = static_cast<firebase::admob::InterstitialAd*>(user_data);
if (future.error() == firebase::admob::kAdMobErrorNone) {
interstitial_ad->LoadAd(my_ad_request);
}
}
使用侦听器来接收广告生命周期事件通知
AdMob 提供了一个抽象类 BannerView::Listener
,您可以继承这个类并将其传递给 BannerView::SetListener()
方法,以便在横幅广告视图的展示状态和边框发生更改时能收到通知。对于插页式广告,AdMob 也提供了一个类似的抽象类 InterstitialAd::Listener
,您可以继承这个类,以便在插页式广告的展示状态发生更改时能收到通知。
下面是继承了 BannerView::Listener
类的一个类的示例实现代码(对于插页式广告,可以使用与此类似的实现代码):
class ExampleBannerViewListener : public firebase::admob::BannerView::Listener {public: ExampleBannerViewListener() {} void OnPresentationStateChanged( firebase::admob::BannerView* banner_view, firebase::admob::BannerView::PresentationState state) override { // This method gets called when the banner view's presentation // state changes. } void OnBoundingBoxChanged( firebase::admob::BannerView* banner_view, firebase::admob::BoundingBox box) override { // This method gets called when the banner view's bounding box // changes. }};
使用入门
您可以在自己的 C++ 应用中使用 AdMob 来展示广告。本指南将向您介绍如何与 Firebase 集成以及如何与 Google Mobile Ads SDK 互动。
如果这是您首次依据本指南进行操作,我们建议您下载 AdMob 测试应用并利用它进行学习。
与 Firebase 集成
完成针对 iOS 进行设置或针对 Android 进行设置部分中的步骤,将 AdMob 和 Firebase 添加到您的 C++ 应用中。
注意:如果您使用的是 AdMob 测试应用,则下列步骤已经替您完成。您应该现在就可以运行该测试应用。
在您应用的 C++ 代码中包含以下头文件:
#include "firebase/admob.h"
#include "firebase/admob/types.h"
#include "firebase/app.h"
#include "firebase/future.h"
将以下代码添加到您应用的 C++ 代码中,以使用 AdMob 应用 ID 初始化 AdMob 库(这段代码应在创建横幅广告视图或插页式广告之前执行):
#if defined(__ANDROID__)// Create the Firebase app.firebase::App* app = firebase::App::Create(firebase::AppOptions(), your_jni_env, your_android_activity);// Your Android AdMob app ID.const char* kAdMobAppID = "ca-app-pub-XXXXXXXXXXXXXXXX~NNNNNNNNNN";#else// Create the Firebase app.firebase::App* app = firebase::App::Create(firebase::AppOptions());// Your iOS AdMob app ID.const char* kAdMobAppID = "ca-app-pub-XXXXXXXXXXXXXXXX~NNNNNNNNNN";#endif // __ANDROID__// Initialize the AdMob library with your AdMob app ID.firebase::admob::Initialize(*app, kAdMobAppID);
注意
:AdMob 应用 ID 是移动应用在 AdMob 控制台中注册时获得的唯一标识符。在应用启动时初始化 Google Mobile Ads SDK 可便于 SDK 获取应用级设置,并尽早执行配置任务。这样有助于减少初始广告请求的延迟时间。
与 Google Mobile Ads SDK 互动
设置广告单元 ID
在编写 iOS 和 Android 上都能支持的 C++ 代码时,您可能需要使用预处理器指令来定义只应在某个特定操作系统上编译的代码。要在 iOS 和 Android 上展示横幅广告和插页式广告,我们建议您为每个操作系统和每个唯一的广告展示位置创建一个新的广告单元 ID。我们已针对 iOS 和 Android 操作系统创建了以下广告单元 ID,并将这些 ID 配置为始终投放测试广告:
#if defined(__ANDROID__)
// Android ad unit IDs
const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111";
const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/1033173712";
#else
// iOS ad unit IDs
const char* kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716";
const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/4411468910";
#endif
设置横幅广告视图
将以下头文件添加到应用的 C++ 代码中:
#include "firebase/admob/banner_view.h"
声明并实例化一个 BannerView
对象:
firebase::admob::BannerView* banner_view;
banner_view = new firebase::admob::BannerView();
创建一个 AdSize
并初始化该横幅广告视图:
firebase::admob::AdSize ad_size;ad_size.ad_size_type = firebase::admob::kAdSizeStandard;ad_size.width = 320;ad_size.height = 50;// my_ad_parent is a reference to an iOS UIView or an Android Activity.// This is the parent UIView or Activity of the banner view.banner_view->Initialize(static_cast<firebase::admob::AdParent>(my_ad_parent), kBannerAdUnit, ad_size);
设置插页式广告
将以下头文件添加到应用的 C++ 代码中:
#include "firebase/admob/interstitial_ad.h"
声明并实例化一个 InterstitialAd
对象:
firebase::admob::InterstitialAd* interstitial_ad;interstitial_ad = new firebase::admob::InterstitialAd();
初始化该插页式广告:
// my_ad_parent is a reference to an iOS UIView or an Android Activity.
// This is the parent UIView or Activity of the interstitial ad.
interstitial_ad->Initialize(static_cast<firebase::admob::AdParent>(my_ad_parent), kInterstitialAdUnit);
创建 AdMob 广告请求
您可以使用 AdMob 库为广告请求提供自定义定位信息。通过设置一个 AdRequest
结构体的若干成员即可完成上述操作。然后,再将该结构体传递给 BannerView::LoadAd()
或 InterstitialAd::LoadAd()
方法。
如需了解有关如何进行广告定位和自定义广告请求的一般信息,请参阅我们的 iOS 和 Android 定位指南。
以下就是 BannerView
和 InterstitialAd
用来发出广告请求的 AdRequest
结构体:
struct AdRequest { const char **test_device_ids; unsigned int test_device_id_count; const char **keywords; unsigned int keyword_count; const KeyValuePair *extras; unsigned int extras_count; int birthday_day; int birthday_month; int birthday_year; Gender gender; ChildDirectedTreatmentState tagged_for_child_directed_treatment;};
声明并初始化该 AdRequest
结构体:
// Initialize all the AdRequest struct member values to zero.
firebase::admob::AdRequest my_ad_request = {};
以下代码设置了 AdRequest
结构体的成员值,以便向广告请求中添加定位信息:
// 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;// 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[] = {"2077ef9a63d2b398840261c8221a0c9b", "098fe087d987c9a878965454a65654d7"};my_ad_request.test_device_id_count = sizeof(kTestDeviceIDs) / sizeof(kTestDeviceIDs[0]);my_ad_request.test_device_ids = kTestDeviceIDs;
将 AdRequest
结构体传递给 BannerView::LoadAd()
和 Interstitial::LoadAd()
方法:
banner_view->LoadAd(my_ad_request);
interstitial_ad->LoadAd(my_ad_request);
Note: A single `AdRequest` struct can be reused for multiple calls.
使用 Future 来监控方法调用的完成状态
Future 为您提供了一种用来确定您之前 BannerView
或 InterstitialAd
方法调用的完成状态的方法。例如,当调用 InterstitialAd::LoadAd()
方法时,系统会创建并返回一个新的 Future。应用可以通过轮询 Future 的状态来确定广告何时加载完毕。当 Future 变成已完成状态后,在您的应用下一次自然停止时就可以展示插页式广告了。
BannerView
和 InterstitialAd
类中的大多数方法都有一个对应的“last result”(上次结果)方法,应用可以使用这些方法来获取某个给定操作的最新 Future。例如,InterstitialAd::LoadAd()
方法就有一个名为 InterstitialAd::LoadAdLastResult()
的对应方法。该方法会返回一个 Future 对象,此对象可用于检查上次调用 InterstitialAd::LoadAd()
方法后的状态。
类似地,应用可以使用 BannerView::InitializeLastResult()
方法来获取一个 Future 对象,该对象可显示上次调用 BannerView::Initialize()
方法后的状态(以及错误代码,如果有的话)。如果其状态为已完成,并且错误代码是 firebase::admob::kAdMobErrorNone
,那么您就可以通过调用 BannerView::Show()
方法来显示横幅广告视图:
if (banner_view->InitializeLastResult().status() == firebase::kFutureStatusComplete && banner_view->InitializeLastResult().error() == firebase::admob::kAdMobErrorNone) { banner_view->Show();}
上次调用 BannerView::Show()
方法后 Future 的状态变成已完成之后,您就可以将一个广告加载到横幅广告视图中:
if (banner_view->ShowLastResult().status() ==
firebase::kFutureStatusComplete &&
banner_view->ShowLastResult().error() ==
firebase::admob::kAdMobErrorNone) {
banner_view->LoadAd(my_ad_request);
}
对于插页式广告,则可使用 InterstitialAd::InitializeLastResult()
方法来获取一个 Future 对象,该对象可显示上次调用 InterstitialAd::Initialize()
方法后的状态(以及错误代码,如果有的话)。如果其状态为已完成,并且错误代码为 firebase::admob::kAdMobErrorNone
,您就可以加载插页式广告了:
if (interstitial_ad->InitializeLastResult().status() == firebase::kFutureStatusComplete && interstitial_ad->InitializeLastResult().error() == firebase::admob::kAdMobErrorNone) { interstitial_ad->LoadAd(my_ad_request);}
上次调用 InterstitialAd::LoadAd()
方法后 Future 的状态变成已完成之后,您就可以在应用下一次自然停止时展示插页式广告了:
if (interstitial_ad->LoadAdLastResult().status() ==
firebase::kFutureStatusComplete &&
interstitial_ad->LoadAdLastResult().error() ==
firebase::admob::kAdMobErrorNone) {
interstitial_ad->Show();
}
您还可以注册当 Future 变成已完成状态时要调用的回调函数。以下代码段使用了一个函数指针来实现回调:
// Initialize the interstitial ad.interstitial_ad->Initialize(static_cast<firebase::admob::AdParent>(my_ad_parent), kInterstitialAdUnit);// Registers the OnCompletion callback. user_data is a pointer that is passed verbatim// to the callback as a void*. In this example, we pass the interstitial ad object to be// used in the OnCompletionCallback function.interstitial_ad->InitializeLastResult().OnCompletion(OnCompletionCallback, interstitial_ad /*user_data*/);// The OnCompletion callback function.static void OnCompletionCallback(const firebase::Future<void>& future, void* user_data) { // Called when the Future is completed for the last call to the InterstitialAd::Initialize() // method. If the error code is firebase::admob::kAdMobErrorNone, then you're ready to // load the interstitial ad. firebase::admob::InterstitialAd *interstitial_ad = static_cast<firebase::admob::InterstitialAd*>(user_data); if (future.error() == firebase::admob::kAdMobErrorNone) { interstitial_ad->LoadAd(my_ad_request); }}
使用侦听器来接收广告生命周期事件通知
AdMob 提供了一个抽象类 BannerView::Listener
,您可以继承这个类并将其传递给 BannerView::SetListener()
方法,以便在横幅广告视图的展示状态和边框发生更改时能收到通知。对于插页式广告,AdMob 也提供了一个类似的抽象类 InterstitialAd::Listener
,您可以继承这个类,以便在插页式广告的展示状态发生更改时能收到通知。
下面是继承了 BannerView::Listener
类的一个类的示例实现代码(对于插页式广告,可以使用与此类似的实现代码):
class ExampleBannerViewListener
: public firebase::admob::BannerView::Listener {
public:
ExampleBannerViewListener() {}
void OnPresentationStateChanged(
firebase::admob::BannerView* banner_view,
firebase::admob::BannerView::PresentationState state) override {
// This method gets called when the banner view's presentation
// state changes.
}
void OnBoundingBoxChanged(
firebase::admob::BannerView* banner_view,
firebase::admob::BoundingBox box) override {
// This method gets called when the banner view's bounding box
// changes.
}
};