Skip to content

Commit 3fd90d5

Browse files
Internal Updates (firebase#1539)
* Internal Updates
1 parent 0e6ec24 commit 3fd90d5

File tree

8 files changed

+188
-2
lines changed

8 files changed

+188
-2
lines changed

gma/integration_test/src/integration_test.cc

+17
Original file line numberDiff line numberDiff line change
@@ -2170,6 +2170,10 @@ TEST_F(FirebaseGmaTest, TestNativeRecordImpression) {
21702170
WaitForCompletion(native_ad->Initialize(app_framework::GetWindowContext()),
21712171
"Initialize");
21722172

2173+
// Set the listener.
2174+
TestAdListener ad_listener;
2175+
native_ad->SetAdListener(&ad_listener);
2176+
21732177
// When the NativeAd is initialized, load an ad.
21742178
firebase::Future<firebase::gma::AdResult> load_ad_future =
21752179
native_ad->LoadAd(kNativeAdUnit, GetAdRequest());
@@ -2199,6 +2203,10 @@ TEST_F(FirebaseGmaTest, TestNativeRecordImpression) {
21992203
firebase::gma::kAdErrorCodeInvalidRequest);
22002204
#endif
22012205

2206+
// Use an allowlisted Ad unit ID that can record an impression, to verify
2207+
// the impression count while testing locally.
2208+
EXPECT_EQ(ad_listener.num_on_ad_impression_, 0);
2209+
22022210
firebase::Variant str_variant =
22032211
firebase::Variant::FromMutableString("test");
22042212
WaitForCompletion(native_ad->RecordImpression(str_variant),
@@ -2221,6 +2229,10 @@ TEST_F(FirebaseGmaTest, TestNativePerformClick) {
22212229
WaitForCompletion(native_ad->Initialize(app_framework::GetWindowContext()),
22222230
"Initialize");
22232231

2232+
// Set the listener.
2233+
TestAdListener ad_listener;
2234+
native_ad->SetAdListener(&ad_listener);
2235+
22242236
// When the NativeAd is initialized, load an ad.
22252237
firebase::Future<firebase::gma::AdResult> load_ad_future =
22262238
native_ad->LoadAd(kNativeAdUnit, GetAdRequest());
@@ -2241,6 +2253,11 @@ TEST_F(FirebaseGmaTest, TestNativePerformClick) {
22412253
// Android and iOS doesn't have a return type for this API.
22422254
WaitForCompletion(native_ad->PerformClick(click_payload), "PerformClick");
22432255

2256+
// Test Ad unit IDs are not allowlisted to use PerformClick API and the
2257+
// request is expected to be rejected by the server. Use an allowlisted Ad
2258+
// unit ID to verify the ad click count while testing locally.
2259+
EXPECT_EQ(ad_listener.num_on_ad_clicked_, 0);
2260+
22442261
firebase::Variant str_variant =
22452262
firebase::Variant::FromMutableString("test");
22462263
WaitForCompletion(native_ad->PerformClick(str_variant), "PerformClick 2",

gma/src/android/gma_android.cc

+45
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,43 @@ void JNI_NativeAd_completeLoadedAd(JNIEnv* env, jclass clazz, jlong data_ptr,
973973
env->DeleteLocalRef(j_response_info);
974974
}
975975

976+
void JNI_NativeAd_notifyAdClicked(JNIEnv* env, jclass clazz, jlong data_ptr) {
977+
FIREBASE_ASSERT(env);
978+
FIREBASE_ASSERT(data_ptr);
979+
980+
firebase::gma::internal::NativeAdInternal* internal =
981+
reinterpret_cast<firebase::gma::internal::NativeAdInternal*>(data_ptr);
982+
internal->NotifyListenerAdClicked();
983+
}
984+
985+
void JNI_NativeAd_notifyAdClosed(JNIEnv* env, jclass clazz, jlong data_ptr) {
986+
FIREBASE_ASSERT(env);
987+
FIREBASE_ASSERT(data_ptr);
988+
989+
firebase::gma::internal::NativeAdInternal* internal =
990+
reinterpret_cast<firebase::gma::internal::NativeAdInternal*>(data_ptr);
991+
internal->NotifyListenerAdClosed();
992+
}
993+
994+
void JNI_NativeAd_notifyAdImpression(JNIEnv* env, jclass clazz,
995+
jlong data_ptr) {
996+
FIREBASE_ASSERT(env);
997+
FIREBASE_ASSERT(data_ptr);
998+
999+
firebase::gma::internal::NativeAdInternal* internal =
1000+
reinterpret_cast<firebase::gma::internal::NativeAdInternal*>(data_ptr);
1001+
internal->NotifyListenerAdImpression();
1002+
}
1003+
1004+
void JNI_NativeAd_notifyAdOpened(JNIEnv* env, jclass clazz, jlong data_ptr) {
1005+
FIREBASE_ASSERT(env);
1006+
FIREBASE_ASSERT(data_ptr);
1007+
1008+
firebase::gma::internal::NativeAdInternal* internal =
1009+
reinterpret_cast<firebase::gma::internal::NativeAdInternal*>(data_ptr);
1010+
internal->NotifyListenerAdOpened();
1011+
}
1012+
9761013
void JNI_NativeImage_completeLoadedImage(JNIEnv* env, jclass clazz,
9771014
jlong data_ptr,
9781015
jobject j_image_bytes) {
@@ -1260,6 +1297,14 @@ bool RegisterNatives() {
12601297
reinterpret_cast<void*>(&JNI_completeLoadAdError)},
12611298
{"completeNativeLoadAdInternalError", "(JILjava/lang/String;)V",
12621299
reinterpret_cast<void*>(&JNI_completeLoadAdInternalError)},
1300+
{"notifyAdClicked", "(J)V",
1301+
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdClicked)},
1302+
{"notifyAdClosed", "(J)V",
1303+
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdClosed)},
1304+
{"notifyAdImpression", "(J)V",
1305+
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdImpression)},
1306+
{"notifyAdOpened", "(J)V",
1307+
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdOpened)},
12631308
};
12641309

12651310
static const JNINativeMethod kNativeImageMethods[] = {

gma/src/common/native_ad.cc

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ Future<AdResult> NativeAd::LoadAdLastResult() const {
7979
return internal_->GetLoadAdLastResult();
8080
}
8181

82+
void NativeAd::SetAdListener(AdListener* listener) {
83+
internal_->SetAdListener(listener);
84+
}
85+
8286
const NativeAdImage& NativeAd::icon() const { return internal_->icon(); }
8387

8488
const std::vector<NativeAdImage>& NativeAd::images() const {

gma/src/common/native_ad_internal.cc

+34-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ namespace gma {
3838
namespace internal {
3939

4040
NativeAdInternal::NativeAdInternal(NativeAd* base)
41-
: base_(base), future_data_(kNativeAdFnCount) {}
41+
: base_(base), future_data_(kNativeAdFnCount), ad_listener_(nullptr) {}
4242

4343
NativeAdInternal* NativeAdInternal::CreateInstance(NativeAd* base) {
4444
#if FIREBASE_PLATFORM_ANDROID
@@ -61,6 +61,39 @@ Future<AdResult> NativeAdInternal::GetLoadAdLastResult() {
6161
future_data_.future_impl.LastResult(kNativeAdFnLoadAd));
6262
}
6363

64+
void NativeAdInternal::SetAdListener(AdListener* listener) {
65+
MutexLock lock(listener_mutex_);
66+
ad_listener_ = listener;
67+
}
68+
69+
void NativeAdInternal::NotifyListenerAdClicked() {
70+
MutexLock lock(listener_mutex_);
71+
if (ad_listener_ != nullptr) {
72+
ad_listener_->OnAdClicked();
73+
}
74+
}
75+
76+
void NativeAdInternal::NotifyListenerAdClosed() {
77+
MutexLock lock(listener_mutex_);
78+
if (ad_listener_ != nullptr) {
79+
ad_listener_->OnAdClosed();
80+
}
81+
}
82+
83+
void NativeAdInternal::NotifyListenerAdImpression() {
84+
MutexLock lock(listener_mutex_);
85+
if (ad_listener_ != nullptr) {
86+
ad_listener_->OnAdImpression();
87+
}
88+
}
89+
90+
void NativeAdInternal::NotifyListenerAdOpened() {
91+
MutexLock lock(listener_mutex_);
92+
if (ad_listener_ != nullptr) {
93+
ad_listener_->OnAdOpened();
94+
}
95+
}
96+
6497
void NativeAdInternal::insert_image(const NativeAdImage& image,
6598
const std::string& image_type) {
6699
if (image_type == "icon") {

gma/src/common/native_ad_internal.h

+15
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ class NativeAdInternal {
6161
// Retrieves the most recent AdResult future for the LoadAd function.
6262
Future<AdResult> GetLoadAdLastResult();
6363

64+
// Sets an AdListener for this ad view.
65+
virtual void SetAdListener(AdListener* listener);
66+
67+
// Notifies the Ad listener (if one exists) that an event has occurred.
68+
void NotifyListenerAdClicked();
69+
void NotifyListenerAdClosed();
70+
void NotifyListenerAdImpression();
71+
void NotifyListenerAdOpened();
72+
6473
// Returns true if the NativeAd has been initialized.
6574
virtual bool is_initialized() const = 0;
6675

@@ -101,6 +110,9 @@ class NativeAdInternal {
101110
// Future data used to synchronize asynchronous calls.
102111
FutureData future_data_;
103112

113+
// Listener for NativeAd Lifecycle event callbacks.
114+
AdListener* ad_listener_;
115+
104116
// Tracks the native ad icon asset.
105117
NativeAdImage icon_;
106118

@@ -109,6 +121,9 @@ class NativeAdInternal {
109121

110122
// Tracks the native ad choices icon asset.
111123
NativeAdImage adchoices_icon_;
124+
125+
// Lock object for accessing ad_listener_.
126+
Mutex listener_mutex_;
112127
};
113128

114129
} // namespace internal

gma/src/include/firebase/gma/internal/native_ad.h

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ class NativeAd {
6767
/// LoadAd.
6868
Future<AdResult> LoadAdLastResult() const;
6969

70+
/// Sets an AdListener for this native ad.
71+
///
72+
/// @param[in] listener An AdListener object which will be invoked
73+
/// when lifecycle events occur on this NativeAd.
74+
void SetAdListener(AdListener* listener);
75+
7076
/// Returns the associated icon asset of the native ad.
7177
const NativeAdImage& icon() const;
7278

gma/src/ios/FADNativeDelegate.mm

+18
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,22 @@ - (void)adLoader:(GADAdLoader *)adLoader didReceiveNativeAd:(GADNativeAd *)nativ
5050
_nativeAd->NativeAdDidReceiveAd(nativeAd);
5151
}
5252

53+
#pragma mark GADNativeAdDelegate implementation
54+
55+
- (void)nativeAdDidRecordClick:(nonnull GADNativeAd *)nativeAd {
56+
_nativeAd->NotifyListenerAdClicked();
57+
}
58+
59+
- (void)nativeAdDidRecordImpression:(nonnull GADNativeAd *)nativeAd {
60+
_nativeAd->NotifyListenerAdImpression();
61+
}
62+
63+
- (void)nativeAdWillPresentScreen:(nonnull GADNativeAd *)nativeAd {
64+
_nativeAd->NotifyListenerAdOpened();
65+
}
66+
67+
- (void)nativeAdDidDismissScreen:(nonnull GADNativeAd *)nativeAd {
68+
_nativeAd->NotifyListenerAdClosed();
69+
}
70+
5371
@end

gma/src_java/com/google/firebase/gma/internal/cpp/NativeAdHelper.java

+49-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public void run() {
9898
});
9999
}
100100

101-
/** Disconnect the helper from the interstital ad. */
101+
/** Disconnect the helper from the native ad. */
102102
public void disconnect() {
103103
synchronized (mNativeLock) {
104104
mNativeAdInternalPtr = CPP_NULLPTR;
@@ -263,6 +263,42 @@ public void onNativeAdLoaded(NativeAd ad) {
263263
}
264264
}
265265
}
266+
267+
@Override
268+
public void onAdClicked() {
269+
synchronized (mNativeLock) {
270+
if (mNativeAdInternalPtr != CPP_NULLPTR) {
271+
notifyAdClicked(mNativeAdInternalPtr);
272+
}
273+
}
274+
}
275+
276+
@Override
277+
public void onAdImpression() {
278+
synchronized (mNativeLock) {
279+
if (mNativeAdInternalPtr != CPP_NULLPTR) {
280+
notifyAdImpression(mNativeAdInternalPtr);
281+
}
282+
}
283+
}
284+
285+
@Override
286+
public void onAdClosed() {
287+
synchronized (mNativeLock) {
288+
if (mNativeAdInternalPtr != CPP_NULLPTR) {
289+
notifyAdClosed(mNativeAdInternalPtr);
290+
}
291+
}
292+
}
293+
294+
@Override
295+
public void onAdOpened() {
296+
synchronized (mNativeLock) {
297+
if (mNativeAdInternalPtr != CPP_NULLPTR) {
298+
notifyAdOpened(mNativeAdInternalPtr);
299+
}
300+
}
301+
}
266302
}
267303

268304
/** Native callback to instruct the C++ wrapper to complete the corresponding future. */
@@ -287,4 +323,16 @@ public static native void completeNativeLoadAdError(
287323
*/
288324
public static native void completeNativeLoadAdInternalError(
289325
long nativeInternalPtr, int gmaErrorCode, String errorMessage);
326+
327+
/** Native callback to notify the C++ wrapper of an ad clicked event */
328+
public static native void notifyAdClicked(long nativeInternalPtr);
329+
330+
/** Native callback to notify the C++ wrapper of an ad closed event */
331+
public static native void notifyAdClosed(long nativeInternalPtr);
332+
333+
/** Native callback to notify the C++ wrapper of an ad impression event */
334+
public static native void notifyAdImpression(long nativeInternalPtr);
335+
336+
/** Native callback to notify the C++ wrapper of an ad opened event */
337+
public static native void notifyAdOpened(long nativeInternalPtr);
290338
}

0 commit comments

Comments
 (0)