21
21
22
22
#include < cstdarg>
23
23
#include < cstddef>
24
+ #include < string>
24
25
25
26
#include " admob/admob_resources.h"
26
27
#include " admob/src/android/ad_request_converter.h"
@@ -42,19 +43,51 @@ METHOD_LOOKUP_DEFINITION(
42
43
" com/google/firebase/admob/internal/cpp/BannerViewHelper" ,
43
44
BANNERVIEWHELPER_METHODS);
44
45
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
+
45
57
namespace internal {
46
58
47
59
BannerViewInternalAndroid::BannerViewInternalAndroid (BannerView* base)
48
- : BannerViewInternal(base), helper_(nullptr ), bounding_box_() {
60
+ : BannerViewInternal(base),
61
+ helper_ (nullptr ),
62
+ initialized_(false ),
63
+ bounding_box_() {
49
64
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);
50
77
51
78
jobject helper_ref = env->NewObject (
52
79
banner_view_helper::GetClass (),
53
80
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);
55
85
FIREBASE_ASSERT (helper_ref);
86
+
87
+ ad_view_ = env->NewGlobalRef (adview_ref);
88
+ env->DeleteLocalRef (adview_ref);
89
+
56
90
helper_ = env->NewGlobalRef (helper_ref);
57
- FIREBASE_ASSERT (helper_);
58
91
env->DeleteLocalRef (helper_ref);
59
92
}
60
93
@@ -66,37 +99,131 @@ void DestroyOnDeleteCallback(const Future<void>& result, void* sem_data) {
66
99
}
67
100
68
101
BannerViewInternalAndroid::~BannerViewInternalAndroid () {
69
- JNIEnv* env = ::firebase::admob::GetJNI ();
70
-
71
102
DestroyInternalData ();
72
103
73
104
Semaphore semaphore (0 );
74
105
InvokeNullary (kBannerViewFnDestroyOnDelete , banner_view_helper::kDestroy )
75
106
.OnCompletion (DestroyOnDeleteCallback, &semaphore);
76
-
77
107
semaphore.Wait ();
108
+
109
+ JNIEnv* env = ::firebase::admob::GetJNI ();
110
+
111
+ env->DeleteGlobalRef (ad_view_);
112
+ ad_view_ = nullptr ;
113
+
78
114
env->DeleteGlobalRef (helper_);
79
115
helper_ = nullptr ;
80
116
}
81
117
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
+
82
202
Future<void > BannerViewInternalAndroid::Initialize (AdParent parent,
83
203
const char * ad_unit_id,
84
204
AdSize size) {
85
205
FutureCallbackData* callback_data =
86
206
CreateFutureCallbackData (&future_data_, kBannerViewFnInitialize );
87
207
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
+
88
214
JNIEnv* env = ::firebase::admob::GetJNI ();
89
215
jobject activity = ::firebase::admob::GetActivity ();
90
216
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);
100
227
101
228
return GetLastResult (kBannerViewFnInitialize );
102
229
}
@@ -111,7 +238,6 @@ Future<void> BannerViewInternalAndroid::LoadAd(const AdRequest& request) {
111
238
::firebase::admob::GetJNI ()->CallVoidMethod(
112
239
helper_, banner_view_helper::GetMethodId(banner_view_helper::kLoadAd ),
113
240
reinterpret_cast<jlong>(callback_data), request_ref);
114
-
115
241
return GetLastResult (kBannerViewFnLoadAd );
116
242
}
117
243
0 commit comments