Skip to content

Commit d4a91b1

Browse files
authored
Updates to Admob Android to reduce usage of BannerViewHelper.java (#624)
* removed some BannerViewHelper code, the rest requires upcoming listener revamp * added <string.h> include to banner_view_internal_android.cc
1 parent 67678b8 commit d4a91b1

File tree

4 files changed

+189
-67
lines changed

4 files changed

+189
-67
lines changed

admob/src/android/admob_android.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,13 @@ InitResult Initialize(JNIEnv* env, jobject activity) {
130130

131131
if (!(mobile_ads::CacheMethodIds(env, activity) &&
132132
ad_request_builder::CacheMethodIds(env, activity) &&
133+
ad_size::CacheMethodIds(env, activity) &&
134+
ad_view::CacheMethodIds(env, activity) &&
133135
request_config_builder::CacheMethodIds(env, activity) &&
134136
banner_view_helper::CacheClassFromFiles(env, activity,
135137
&embedded_files) != nullptr &&
136138
banner_view_helper::CacheMethodIds(env, activity) &&
139+
banner_view_helper_ad_view_listener::CacheMethodIds(env, activity) &&
137140
interstitial_ad_helper::CacheClassFromFiles(
138141
env, activity, &embedded_files) != nullptr &&
139142
interstitial_ad_helper::CacheMethodIds(env, activity) &&
@@ -156,8 +159,11 @@ InitResult Initialize(JNIEnv* env, jobject activity) {
156159
void ReleaseClasses(JNIEnv* env) {
157160
mobile_ads::ReleaseClass(env);
158161
ad_request_builder::ReleaseClass(env);
162+
ad_size::ReleaseClass(env);
163+
ad_view::ReleaseClass(env);
159164
request_config_builder::ReleaseClass(env);
160165
banner_view_helper::ReleaseClass(env);
166+
banner_view_helper_ad_view_listener::ReleaseClass(env);
161167
interstitial_ad_helper::ReleaseClass(env);
162168
}
163169

admob/src/android/banner_view_internal_android.cc

Lines changed: 142 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <cstdarg>
2323
#include <cstddef>
24+
#include <string>
2425

2526
#include "admob/admob_resources.h"
2627
#include "admob/src/android/ad_request_converter.h"
@@ -42,19 +43,51 @@ METHOD_LOOKUP_DEFINITION(
4243
"com/google/firebase/admob/internal/cpp/BannerViewHelper",
4344
BANNERVIEWHELPER_METHODS);
4445

46+
METHOD_LOOKUP_DEFINITION(
47+
banner_view_helper_ad_view_listener,
48+
"com/google/firebase/admob/internal/cpp/BannerViewHelper$AdViewListener",
49+
BANNERVIEWHELPER_ADVIEWLISTENER_METHODS);
50+
51+
METHOD_LOOKUP_DEFINITION(ad_view, "com/google/android/gms/ads/AdView",
52+
AD_VIEW_METHODS);
53+
54+
METHOD_LOOKUP_DEFINITION(ad_size, "com/google/android/gms/ads/AdSize",
55+
AD_SIZE_METHODS);
56+
4557
namespace internal {
4658

4759
BannerViewInternalAndroid::BannerViewInternalAndroid(BannerView* base)
48-
: BannerViewInternal(base), helper_(nullptr), bounding_box_() {
60+
: BannerViewInternal(base),
61+
helper_(nullptr),
62+
initialized_(false),
63+
bounding_box_() {
4964
JNIEnv* env = ::firebase::admob::GetJNI();
65+
FIREBASE_ASSERT(env);
66+
67+
jobject activity = ::firebase::admob::GetActivity();
68+
FIREBASE_ASSERT(activity);
69+
70+
jobject adview_ref =
71+
env->NewObject(ad_view::GetClass(),
72+
ad_view::GetMethodId(ad_view::kConstructor), activity);
73+
74+
bool jni_exception = util::CheckAndClearJniExceptions(env);
75+
FIREBASE_ASSERT(!jni_exception);
76+
FIREBASE_ASSERT(adview_ref);
5077

5178
jobject helper_ref = env->NewObject(
5279
banner_view_helper::GetClass(),
5380
banner_view_helper::GetMethodId(banner_view_helper::kConstructor),
54-
reinterpret_cast<jlong>(this));
81+
reinterpret_cast<jlong>(this), adview_ref);
82+
83+
jni_exception = util::CheckAndClearJniExceptions(env);
84+
FIREBASE_ASSERT(!jni_exception);
5585
FIREBASE_ASSERT(helper_ref);
86+
87+
ad_view_ = env->NewGlobalRef(adview_ref);
88+
env->DeleteLocalRef(adview_ref);
89+
5690
helper_ = env->NewGlobalRef(helper_ref);
57-
FIREBASE_ASSERT(helper_);
5891
env->DeleteLocalRef(helper_ref);
5992
}
6093

@@ -66,37 +99,131 @@ void DestroyOnDeleteCallback(const Future<void>& result, void* sem_data) {
6699
}
67100

68101
BannerViewInternalAndroid::~BannerViewInternalAndroid() {
69-
JNIEnv* env = ::firebase::admob::GetJNI();
70-
71102
DestroyInternalData();
72103

73104
Semaphore semaphore(0);
74105
InvokeNullary(kBannerViewFnDestroyOnDelete, banner_view_helper::kDestroy)
75106
.OnCompletion(DestroyOnDeleteCallback, &semaphore);
76-
77107
semaphore.Wait();
108+
109+
JNIEnv* env = ::firebase::admob::GetJNI();
110+
111+
env->DeleteGlobalRef(ad_view_);
112+
ad_view_ = nullptr;
113+
78114
env->DeleteGlobalRef(helper_);
79115
helper_ = nullptr;
80116
}
81117

118+
struct BannerViewInternalInitializeData {
119+
// Thread-safe call data.
120+
BannerViewInternalInitializeData()
121+
: activity_global(nullptr),
122+
ad_view(nullptr),
123+
banner_view_helper(nullptr) {}
124+
~BannerViewInternalInitializeData() {
125+
JNIEnv* env = GetJNI();
126+
env->DeleteGlobalRef(activity_global);
127+
env->DeleteGlobalRef(ad_view);
128+
env->DeleteGlobalRef(banner_view_helper);
129+
}
130+
131+
jobject activity_global;
132+
AdSize ad_size;
133+
std::string ad_unit_id;
134+
jobject ad_view;
135+
jobject banner_view_helper;
136+
FutureCallbackData* callback_data;
137+
};
138+
139+
// This function is run on the main thread and is called in the
140+
// BannerViewInternalAndroid::Initialize() method.
141+
void InitializeBannerViewOnMainThread(void* data) {
142+
BannerViewInternalInitializeData* call_data =
143+
reinterpret_cast<BannerViewInternalInitializeData*>(data);
144+
JNIEnv* env = GetJNI();
145+
FIREBASE_ASSERT(env != nullptr);
146+
147+
jstring ad_unit_id_str = env->NewStringUTF(call_data->ad_unit_id.c_str());
148+
env->CallVoidMethod(call_data->ad_view,
149+
ad_view::GetMethodId(ad_view::kSetAdUnitId),
150+
ad_unit_id_str);
151+
env->DeleteLocalRef(ad_unit_id_str);
152+
153+
bool jni_exception = util::CheckAndClearJniExceptions(env);
154+
FIREBASE_ASSERT(!jni_exception);
155+
156+
jobject ad_size = env->NewObject(
157+
ad_size::GetClass(), ad_size::GetMethodId(ad_size::kConstructor),
158+
call_data->ad_size.width, call_data->ad_size.height);
159+
160+
jni_exception = util::CheckAndClearJniExceptions(env);
161+
FIREBASE_ASSERT(!jni_exception);
162+
163+
env->CallVoidMethod(call_data->ad_view,
164+
ad_view::GetMethodId(ad_view::kSetAdSize), ad_size);
165+
166+
jni_exception = util::CheckAndClearJniExceptions(env);
167+
FIREBASE_ASSERT(!jni_exception);
168+
169+
env->CallVoidMethod(
170+
call_data->banner_view_helper,
171+
banner_view_helper::GetMethodId(banner_view_helper::kInitialize),
172+
call_data->activity_global);
173+
174+
jni_exception = util::CheckAndClearJniExceptions(env);
175+
FIREBASE_ASSERT(!jni_exception);
176+
177+
jobject ad_listener = nullptr;
178+
ad_listener =
179+
env->NewObject(banner_view_helper_ad_view_listener::GetClass(),
180+
banner_view_helper_ad_view_listener::GetMethodId(
181+
banner_view_helper_ad_view_listener::kConstructor),
182+
call_data->banner_view_helper);
183+
184+
jni_exception = util::CheckAndClearJniExceptions(env);
185+
FIREBASE_ASSERT(!jni_exception);
186+
187+
env->CallVoidMethod(call_data->ad_view,
188+
ad_view::GetMethodId(ad_view::kSetAdListener),
189+
ad_listener);
190+
191+
jni_exception = util::CheckAndClearJniExceptions(env);
192+
FIREBASE_ASSERT(!jni_exception);
193+
194+
env->DeleteLocalRef(ad_listener);
195+
196+
CompleteFuture(kAdMobErrorNone, "", call_data->callback_data->future_handle,
197+
call_data->callback_data->future_data);
198+
199+
delete call_data;
200+
}
201+
82202
Future<void> BannerViewInternalAndroid::Initialize(AdParent parent,
83203
const char* ad_unit_id,
84204
AdSize size) {
85205
FutureCallbackData* callback_data =
86206
CreateFutureCallbackData(&future_data_, kBannerViewFnInitialize);
87207

208+
if (initialized_) {
209+
CompleteFuture(kAdMobErrorAlreadyInitialized, "Ad is already initialized.",
210+
callback_data->future_handle, callback_data->future_data);
211+
return GetLastResult(kBannerViewFnInitialize);
212+
}
213+
88214
JNIEnv* env = ::firebase::admob::GetJNI();
89215
jobject activity = ::firebase::admob::GetActivity();
90216

91-
jstring ad_unit_id_str = env->NewStringUTF(ad_unit_id);
92-
93-
env->CallVoidMethod(
94-
helper_, banner_view_helper::GetMethodId(banner_view_helper::kInitialize),
95-
reinterpret_cast<jlong>(callback_data), activity, ad_unit_id_str,
96-
static_cast<jint>(size.ad_size_type), static_cast<jint>(size.width),
97-
static_cast<jint>(size.height));
98-
99-
env->DeleteLocalRef(ad_unit_id_str);
217+
BannerViewInternalInitializeData* call_data =
218+
new BannerViewInternalInitializeData();
219+
call_data->activity_global = env->NewGlobalRef(activity);
220+
call_data->ad_size = size;
221+
call_data->ad_unit_id = ad_unit_id;
222+
call_data->ad_view = env->NewGlobalRef(ad_view_);
223+
call_data->banner_view_helper = env->NewGlobalRef(helper_);
224+
call_data->callback_data = callback_data;
225+
util::RunOnMainThread(env, activity, InitializeBannerViewOnMainThread,
226+
call_data);
100227

101228
return GetLastResult(kBannerViewFnInitialize);
102229
}
@@ -111,7 +238,6 @@ Future<void> BannerViewInternalAndroid::LoadAd(const AdRequest& request) {
111238
::firebase::admob::GetJNI()->CallVoidMethod(
112239
helper_, banner_view_helper::GetMethodId(banner_view_helper::kLoadAd),
113240
reinterpret_cast<jlong>(callback_data), request_ref);
114-
115241
return GetLastResult(kBannerViewFnLoadAd);
116242
}
117243

admob/src/android/banner_view_internal_android.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ namespace admob {
2727
// time spent looking up methods by string.
2828
// clang-format off
2929
#define BANNERVIEWHELPER_METHODS(X) \
30-
X(Constructor, "<init>", "(J)V"), \
31-
X(Initialize, "initialize", \
32-
"(JLandroid/app/Activity;Ljava/lang/String;III)V"), \
30+
X(Constructor, "<init>", "(JLcom/google/android/gms/ads/AdView;)V"), \
31+
X(Initialize, "initialize", "(Landroid/app/Activity;)V"), \
3332
X(LoadAd, "loadAd", "(JLcom/google/android/gms/ads/AdRequest;)V"), \
3433
X(Hide, "hide", "(J)V"), \
3534
X(Show, "show", "(J)V"), \
@@ -44,6 +43,31 @@ namespace admob {
4443

4544
METHOD_LOOKUP_DECLARATION(banner_view_helper, BANNERVIEWHELPER_METHODS);
4645

46+
#define BANNERVIEWHELPER_ADVIEWLISTENER_METHODS(X) \
47+
X(Constructor, "<init>", \
48+
"(Lcom/google/firebase/admob/internal/cpp/BannerViewHelper;)V")
49+
50+
METHOD_LOOKUP_DECLARATION(banner_view_helper_ad_view_listener,
51+
BANNERVIEWHELPER_ADVIEWLISTENER_METHODS);
52+
53+
// clang-format off
54+
#define AD_VIEW_METHODS(X) \
55+
X(Constructor, "<init>", "(Landroid/content/Context;)V"), \
56+
X(SetAdSize, "setAdSize", "(Lcom/google/android/gms/ads/AdSize;)V"), \
57+
X(SetAdUnitId, "setAdUnitId", "(Ljava/lang/String;)V"), \
58+
X(SetAdListener, "setAdListener", \
59+
"(Lcom/google/android/gms/ads/AdListener;)V")
60+
// clang-format on
61+
62+
METHOD_LOOKUP_DECLARATION(ad_view, AD_VIEW_METHODS);
63+
64+
// clang-format off
65+
#define AD_SIZE_METHODS(X) \
66+
X(Constructor, "<init>", "(II)V")
67+
// clang-format on
68+
69+
METHOD_LOOKUP_DECLARATION(ad_size, AD_SIZE_METHODS);
70+
4771
namespace internal {
4872

4973
class BannerViewInternalAndroid : public BannerViewInternal {
@@ -70,6 +94,11 @@ class BannerViewInternalAndroid : public BannerViewInternal {
7094
// SDK.
7195
jobject helper_;
7296

97+
// Reference to the Android AdView object used to display BannerView ads.
98+
jobject ad_view_;
99+
100+
bool initialized_;
101+
73102
// The banner view's current BoundingBox. This value is returned if the banner
74103
// view is hidden and the publisher calls GetBoundingBox().
75104
mutable BoundingBox bounding_box_;

admob/src_java/com/google/firebase/admob/internal/cpp/BannerViewHelper.java

Lines changed: 9 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,6 @@ public class BannerViewHelper implements ViewTreeObserver.OnPreDrawListener {
4949
// C++ nullptr for use with the callbacks.
5050
private static final long CPP_NULLPTR = 0;
5151

52-
// Ad Size Types (matches the AdSizeType enumeration in the public C++
53-
// API). There is only one possible value right now, but this will likely
54-
// increase.
55-
public static final int ADSIZETYPE_STANDARD = 0;
56-
5752
// The number of milliseconds to wait before attempting to create a PopUpWindow to hold an ad.
5853
private static final int WEBVIEW_DELAY_MILLISECONDS = 200;
5954

@@ -120,8 +115,9 @@ public class BannerViewHelper implements ViewTreeObserver.OnPreDrawListener {
120115
private int mDesiredY;
121116

122117
/** Constructor. */
123-
public BannerViewHelper(long bannerViewInternalPtr) {
118+
public BannerViewHelper(long bannerViewInternalPtr, AdView adView) {
124119
mBannerViewInternalPtr = bannerViewInternalPtr;
120+
mAdView = adView;
125121
mCurrentPresentationState = ConstantsHelper.AD_VIEW_PRESENTATION_STATE_HIDDEN;
126122
mDesiredPosition = ConstantsHelper.AD_VIEW_POSITION_TOP_LEFT;
127123
mShouldUseXYForPosition = false;
@@ -137,47 +133,12 @@ public BannerViewHelper(long bannerViewInternalPtr) {
137133
}
138134

139135
/**
140-
* Initializes the {@link BannerView}. This creates the corresponding GMA SDK {@link AdView}
141-
* object and sets it up.
136+
* Initializes the {@link BannerView}. This stores the activity for use with
137+
* callback and load operations.
142138
*/
143-
public void initialize(
144-
final long callbackDataPtr,
145-
Activity activity,
146-
String adUnitID,
147-
int adSizeType,
148-
int width,
149-
int height) {
150-
151-
// There is only one ad size type right now, which is why that parameter goes unused.
152-
mAdSize = new AdSize(width, height);
153-
mActivity = activity;
154-
mAdUnitId = adUnitID;
155-
synchronized (mPopUpLock) {
156-
mPopUpRunnable = null;
157-
}
158-
159-
// Create the AdView on the UI thread.
160-
mActivity.runOnUiThread(
161-
new Runnable() {
162-
@Override
163-
public void run() {
164-
int errorCode;
165-
String errorMessage;
166-
if (mAdView == null) {
167-
errorCode = ConstantsHelper.CALLBACK_ERROR_NONE;
168-
errorMessage = ConstantsHelper.CALLBACK_ERROR_MESSAGE_NONE;
169-
mAdView = new AdView(mActivity);
170-
mAdView.setAdUnitId(mAdUnitId);
171-
mAdView.setAdSize(mAdSize);
172-
mAdView.setAdListener(new AdViewListener());
173-
} else {
174-
errorCode = ConstantsHelper.CALLBACK_ERROR_ALREADY_INITIALIZED;
175-
errorMessage = ConstantsHelper.CALLBACK_ERROR_MESSAGE_ALREADY_INITIALIZED;
176-
}
177-
178-
completeBannerViewFutureCallback(callbackDataPtr, errorCode, errorMessage);
179-
}
180-
});
139+
140+
public void initialize(Activity activity) {
141+
mActivity = activity;
181142
}
182143

183144
/** Destroy/deallocate the {@link PopupWindow} and {@link AdView}. */
@@ -239,7 +200,7 @@ public void loadAd(long callbackDataPtr, final AdRequest request) {
239200

240201
mLoadAdCallbackDataPtr = callbackDataPtr;
241202
}
242-
203+
243204
mActivity.runOnUiThread(
244205
new Runnable() {
245206
@Override
@@ -560,7 +521,7 @@ public void run() {
560521
return true;
561522
}
562523

563-
private class AdViewListener extends AdListener {
524+
public class AdViewListener extends AdListener {
564525
@Override
565526
public void onAdClosed() {
566527
mCurrentPresentationState = ConstantsHelper.AD_VIEW_PRESENTATION_STATE_VISIBLE_WITH_AD;

0 commit comments

Comments
 (0)