Skip to content

Functions to Disable AdMob Automatic Services on iOS #772

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 94 additions & 22 deletions admob/integration_test/src/integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ static const char* kAdNetworkExtrasClassName =
static const char* kAdNetworkExtrasClassName = "GADExtras";
#endif

// Class nname of the GMA SDK returned in initialization results.
#if defined(ANDROID)
const char kAdMobClassName[] = "com.google.android.gms.ads.MobileAds";
#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
const char kAdMobClassName[] = "GADMobileAds";
#else // desktop
const char kAdMobClassName[] = "stub";
#endif

// Used to detect kAdMobErrorAdNetworkClassLoadErrors when loading
// ads.
static const char* kAdNetworkExtrasInvalidClassName = "abc123321cba";
Expand Down Expand Up @@ -151,43 +160,60 @@ class FirebaseAdMobTest : public FirebaseTest {
static firebase::App* shared_app_;
};

// Runs AdMob Tests on methods and functions that should be run
// before AdMob initializes.
class FirebaseAdMobPreInitializationTests : public FirebaseAdMobTest {
public:
FirebaseAdMobPreInitializationTests();
~FirebaseAdMobPreInitializationTests() override;

static void SetUpTestSuite();

void SetUp() override;
};

firebase::App* FirebaseAdMobTest::shared_app_ = nullptr;

void PauseForVisualInspectionAndCallbacks() {
app_framework::ProcessEvents(300);
}

void FirebaseAdMobTest::SetUpTestSuite() {
LogDebug("Initialize Firebase App.");

FindFirebaseConfig(FIREBASE_CONFIG_STRING);

#if defined(ANDROID)
shared_app_ = ::firebase::App::Create(app_framework::GetJniEnv(),
app_framework::GetActivity());
#else
shared_app_ = ::firebase::App::Create();
#endif // defined(ANDROID)

void InitializeAdMob(firebase::App* shared_app) {
LogDebug("Initializing AdMob.");

::firebase::ModuleInitializer initializer;
initializer.Initialize(shared_app_, nullptr,
initializer.Initialize(shared_app, nullptr,
[](::firebase::App* app, void* /* userdata */) {
LogDebug("Try to initialize AdMob");
firebase::InitResult result;
::firebase::admob::Initialize(*app, &result);
return result;
});

WaitForCompletion(initializer.InitializeLastResult(), "Initialize");
FirebaseAdMobTest::WaitForCompletion(initializer.InitializeLastResult(),
"Initialize");

ASSERT_EQ(initializer.InitializeLastResult().error(), 0)
<< initializer.InitializeLastResult().error_message();

LogDebug("Successfully initialized AdMob.");
}

void FirebaseAdMobTest::SetUpTestSuite() {
LogDebug("Initialize Firebase App.");

FindFirebaseConfig(FIREBASE_CONFIG_STRING);

#if defined(ANDROID)
shared_app_ = ::firebase::App::Create(app_framework::GetJniEnv(),
app_framework::GetActivity());
#else
shared_app_ = ::firebase::App::Create();
#endif // defined(ANDROID)

InitializeAdMob(shared_app_);
}

void FirebaseAdMobTest::TearDownTestSuite() {
// Workaround: AdMob does some of its initialization in the main
// thread, so if you terminate it too quickly after initialization
Expand Down Expand Up @@ -247,7 +273,54 @@ firebase::admob::AdRequest FirebaseAdMobTest::GetAdRequest() {
return request;
}

FirebaseAdMobPreInitializationTests::FirebaseAdMobPreInitializationTests() {}

FirebaseAdMobPreInitializationTests::~FirebaseAdMobPreInitializationTests() {}

void FirebaseAdMobPreInitializationTests::SetUp() { FirebaseTest::SetUp(); }

void FirebaseAdMobPreInitializationTests::SetUpTestSuite() {
LogDebug("Initialize Firebase App.");
FindFirebaseConfig(FIREBASE_CONFIG_STRING);
#if defined(ANDROID)
shared_app_ = ::firebase::App::Create(app_framework::GetJniEnv(),
app_framework::GetActivity());
#else
shared_app_ = ::firebase::App::Create();
#endif // defined(ANDROID)
}

// Test cases below.

TEST_F(FirebaseAdMobPreInitializationTests,
TestDisableMediationInitialization) {
// Note: This test should be disabled or put in an entirely different test
// binrary if we ever wish to test mediation in this application.
firebase::admob::DisableMediationInitialization();

// Ensure that AdMob can initialize.
InitializeAdMob(shared_app_);
auto initialize_future = firebase::admob::InitializeLastResult();
WaitForCompletion(initialize_future, "admob::Initialize");
ASSERT_NE(initialize_future.result(), nullptr);
EXPECT_EQ(*initialize_future.result(),
firebase::admob::GetInitializationStatus());

#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
// Check to see that only one Adapter was initialized, the base GMA adapter.
// Note: DisableMediationInitialization is only implemented on iOS.
std::map<std::string, firebase::admob::AdapterStatus> adapter_status =
firebase::admob::GetInitializationStatus().GetAdapterStatusMap();
EXPECT_EQ(adapter_status.size(), 1);
EXPECT_THAT(
adapter_status,
Contains(Pair(
kAdMobClassName,
Property(&firebase::admob::AdapterStatus::is_initialized, true))))
<< "Expected adapter class '" << kAdMobClassName << "' is not loaded.";
#endif
}

TEST_F(FirebaseAdMobTest, TestInitializationStatus) {
// Ensure Initialize()'s result matches GetInitializationStatus().
auto initialize_future = firebase::admob::InitializeLastResult();
Expand All @@ -265,14 +338,6 @@ TEST_F(FirebaseAdMobTest, TestInitializationStatus) {
adapter_status.second.description().c_str());
}

#if defined(ANDROID)
const char kAdMobClassName[] = "com.google.android.gms.ads.MobileAds";
#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
const char kAdMobClassName[] = "GADMobileAds";
#else // desktop
const char kAdMobClassName[] = "stub";
#endif

// Confirm that the default Google Mobile Ads SDK class name shows up in the
// list. It should either be is_initialized = true, or description should say
// "Timeout" (this is a special case we are using to deflake this test on
Expand All @@ -287,6 +352,13 @@ TEST_F(FirebaseAdMobTest, TestInitializationStatus) {
<< "Expected adapter class '" << kAdMobClassName << "' is not loaded.";
}

TEST_F(FirebaseAdMobPreInitializationTests, TestDisableSDKCrashReporting) {
// We can't test to see if this method successfully reconfigures crash
// reporting, but we're still calling it as a sanity check and to ensure
// the symbol exists in the library.
firebase::admob::DisableSDKCrashReporting();
}

TEST_F(FirebaseAdMobTest, TestGetAdRequest) { GetAdRequest(); }

TEST_F(FirebaseAdMobTest, TestGetAdRequestValues) {
Expand Down
4 changes: 4 additions & 0 deletions admob/src/android/admob_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,10 @@ AdapterInitializationStatus GetInitializationStatus() {
}
}

void DisableSDKCrashReporting() {}

void DisableMediationInitialization() {}

void SetRequestConfiguration(
const RequestConfiguration& request_configuration) {
JNIEnv* env = ::firebase::admob::GetJNI();
Expand Down
18 changes: 18 additions & 0 deletions admob/src/include/firebase/admob.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,24 @@ Future<AdapterInitializationStatus> InitializeLastResult();
/// check which adapters have been initialized.
AdapterInitializationStatus GetInitializationStatus();

/// Disables automated SDK crash reporting on iOS. If not called, the SDK
/// records the original exception handler if available and registers a new
/// exception handler. The new exception handler only reports SDK related
/// exceptions and calls the recorded original exception handler.
///
/// This method has no effect on Android.
void DisableSDKCrashReporting();

/// Disables mediation adapter initialization on iOS during initialization of
/// the AdMob SDK. Calling this method may negatively impact your ad
/// performance and should only be called if you will not use AdMob SDK
/// controlled mediation during this app session. This method must be called
/// before initializing the AdMob SDK or loading ads and has no effect once the
/// SDK has been initialized.
///
/// This method has no effect on Android.
void DisableMediationInitialization();

/// Sets the global @ref RequestConfiguration that will be used for
/// every @ref AdRequest during the app's session.
///
Expand Down
8 changes: 8 additions & 0 deletions admob/src/ios/admob_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ static AdapterInitializationStatus PopulateAdapterInitializationStatus(

bool IsInitialized() { return g_initialized; }

void DisableSDKCrashReporting() {
[GADMobileAds.sharedInstance disableSDKCrashReporting];
}

void DisableMediationInitialization() {
[GADMobileAds.sharedInstance disableMediationInitialization];
}

void SetRequestConfiguration(const RequestConfiguration& request_configuration)
{
GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers =
Expand Down
4 changes: 4 additions & 0 deletions admob/src/stub/admob_stub.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ AdapterInitializationStatus GetInitializationStatus() {
}
}

void DisableSDKCrashReporting() {}

void DisableMediationInitialization() {}

bool IsInitialized() { return g_initialized; }

void SetRequestConfiguration(
Expand Down
8 changes: 4 additions & 4 deletions app/src/util_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -818,10 +818,10 @@ std::string JObjectClassName(JNIEnv* env, jobject obj);
jobject StdVectorToJavaList(JNIEnv* env,
const std::vector<std::string>& string_vector);

// Converts a `std::unordered_set<std::string>` to a `java.util.ArrayList<String>`
// Returns a local ref to a List.
jobject StdUnorderedSetToJavaList(JNIEnv* env,
const std::unordered_set<std::string>& string_set);
// Converts a `std::unordered_set<std::string>` to a
// `java.util.ArrayList<String>` Returns a local ref to a List.
jobject StdUnorderedSetToJavaList(
JNIEnv* env, const std::unordered_set<std::string>& string_set);

// Converts an `std::map<const char*, const char*>` to a
// `java.util.Map<String, String>`.
Expand Down
14 changes: 7 additions & 7 deletions app/src/util_ios.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
#ifndef FIREBASE_APP_SRC_UTIL_IOS_H_
#define FIREBASE_APP_SRC_UTIL_IOS_H_

#ifdef __OBJC__

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#include <map>
#include <string>
#include <unordered_set>
#include <vector>

#ifdef __OBJC__

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#include "app/src/include/firebase/variant.h"

namespace firebase {
Expand Down Expand Up @@ -200,8 +200,8 @@ NSMutableArray *StringUnorderedSetToNSMutableArray(

// Convert a NSArray into a vector of strings. Asserts if a non NSString
// object is found in the array.
void NSArrayOfNSStringToVectorOfString(
NSArray *array, std::vector<std::string> *string_vector);
void NSArrayOfNSStringToVectorOfString(NSArray *array,
std::vector<std::string> *string_vector);
Copy link
Contributor Author

@DellaBitta DellaBitta Dec 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#include <vector> is indeed at the top of this file.

... fixed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably the linter either doesn't know that OBJC will be defined, you could move the c++-specific includes outside of that ifdef. Or just ignore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


// Convert a string map to NSDictionary.
NSDictionary *StringMapToNSDictionary(
Expand Down
5 changes: 2 additions & 3 deletions app/src/util_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,15 @@ void ForEachAppDelegateClass(void (^block)(Class)) {
return array;
}

NSMutableArray *StringUnorderedSetToNSMutableArray(
const std::unordered_set<std::string> &set) {
NSMutableArray *StringUnorderedSetToNSMutableArray(const std::unordered_set<std::string> &set) {
NSMutableArray<NSString *> *array = [[NSMutableArray alloc] initWithCapacity:set.size()];
for (auto &element : set) {
[array addObject:StringToNSString(element)];
}
return array;
}

void NSArrayOfNSStringToVectorOfString(NSArray* array, std::vector<std::string>* string_vector) {
void NSArrayOfNSStringToVectorOfString(NSArray *array, std::vector<std::string> *string_vector) {
string_vector->reserve(array.count);
for (id object in array) {
if (![object isKindOfClass:[NSString class]]) {
Expand Down