Skip to content
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

Internal Updates #1539

Merged
merged 2 commits into from
Feb 15, 2024
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
17 changes: 17 additions & 0 deletions gma/integration_test/src/integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2170,6 +2170,10 @@ TEST_F(FirebaseGmaTest, TestNativeRecordImpression) {
WaitForCompletion(native_ad->Initialize(app_framework::GetWindowContext()),
"Initialize");

// Set the listener.
TestAdListener ad_listener;
native_ad->SetAdListener(&ad_listener);

// When the NativeAd is initialized, load an ad.
firebase::Future<firebase::gma::AdResult> load_ad_future =
native_ad->LoadAd(kNativeAdUnit, GetAdRequest());
Expand Down Expand Up @@ -2199,6 +2203,10 @@ TEST_F(FirebaseGmaTest, TestNativeRecordImpression) {
firebase::gma::kAdErrorCodeInvalidRequest);
#endif

// Use an allowlisted Ad unit ID that can record an impression, to verify
// the impression count while testing locally.
EXPECT_EQ(ad_listener.num_on_ad_impression_, 0);

firebase::Variant str_variant =
firebase::Variant::FromMutableString("test");
WaitForCompletion(native_ad->RecordImpression(str_variant),
Expand All @@ -2221,6 +2229,10 @@ TEST_F(FirebaseGmaTest, TestNativePerformClick) {
WaitForCompletion(native_ad->Initialize(app_framework::GetWindowContext()),
"Initialize");

// Set the listener.
TestAdListener ad_listener;
native_ad->SetAdListener(&ad_listener);

// When the NativeAd is initialized, load an ad.
firebase::Future<firebase::gma::AdResult> load_ad_future =
native_ad->LoadAd(kNativeAdUnit, GetAdRequest());
Expand All @@ -2241,6 +2253,11 @@ TEST_F(FirebaseGmaTest, TestNativePerformClick) {
// Android and iOS doesn't have a return type for this API.
WaitForCompletion(native_ad->PerformClick(click_payload), "PerformClick");

// Test Ad unit IDs are not allowlisted to use PerformClick API and the
// request is expected to be rejected by the server. Use an allowlisted Ad
// unit ID to verify the ad click count while testing locally.
EXPECT_EQ(ad_listener.num_on_ad_clicked_, 0);

firebase::Variant str_variant =
firebase::Variant::FromMutableString("test");
WaitForCompletion(native_ad->PerformClick(str_variant), "PerformClick 2",
Expand Down
45 changes: 45 additions & 0 deletions gma/src/android/gma_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,43 @@ void JNI_NativeAd_completeLoadedAd(JNIEnv* env, jclass clazz, jlong data_ptr,
env->DeleteLocalRef(j_response_info);
}

void JNI_NativeAd_notifyAdClicked(JNIEnv* env, jclass clazz, jlong data_ptr) {
FIREBASE_ASSERT(env);
FIREBASE_ASSERT(data_ptr);

firebase::gma::internal::NativeAdInternal* internal =
nakirekommula marked this conversation as resolved.
Show resolved Hide resolved
reinterpret_cast<firebase::gma::internal::NativeAdInternal*>(data_ptr);
internal->NotifyListenerAdClicked();
}

void JNI_NativeAd_notifyAdClosed(JNIEnv* env, jclass clazz, jlong data_ptr) {
FIREBASE_ASSERT(env);
FIREBASE_ASSERT(data_ptr);

firebase::gma::internal::NativeAdInternal* internal =
reinterpret_cast<firebase::gma::internal::NativeAdInternal*>(data_ptr);
internal->NotifyListenerAdClosed();
}

void JNI_NativeAd_notifyAdImpression(JNIEnv* env, jclass clazz,
jlong data_ptr) {
FIREBASE_ASSERT(env);
FIREBASE_ASSERT(data_ptr);

firebase::gma::internal::NativeAdInternal* internal =
reinterpret_cast<firebase::gma::internal::NativeAdInternal*>(data_ptr);
internal->NotifyListenerAdImpression();
}

void JNI_NativeAd_notifyAdOpened(JNIEnv* env, jclass clazz, jlong data_ptr) {
FIREBASE_ASSERT(env);
FIREBASE_ASSERT(data_ptr);

firebase::gma::internal::NativeAdInternal* internal =
reinterpret_cast<firebase::gma::internal::NativeAdInternal*>(data_ptr);
internal->NotifyListenerAdOpened();
}

void JNI_NativeImage_completeLoadedImage(JNIEnv* env, jclass clazz,
jlong data_ptr,
jobject j_image_bytes) {
Expand Down Expand Up @@ -1260,6 +1297,14 @@ bool RegisterNatives() {
reinterpret_cast<void*>(&JNI_completeLoadAdError)},
{"completeNativeLoadAdInternalError", "(JILjava/lang/String;)V",
reinterpret_cast<void*>(&JNI_completeLoadAdInternalError)},
{"notifyAdClicked", "(J)V",
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdClicked)},
{"notifyAdClosed", "(J)V",
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdClosed)},
{"notifyAdImpression", "(J)V",
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdImpression)},
{"notifyAdOpened", "(J)V",
reinterpret_cast<void*>(&JNI_NativeAd_notifyAdOpened)},
};

static const JNINativeMethod kNativeImageMethods[] = {
Expand Down
4 changes: 4 additions & 0 deletions gma/src/common/native_ad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ Future<AdResult> NativeAd::LoadAdLastResult() const {
return internal_->GetLoadAdLastResult();
}

void NativeAd::SetAdListener(AdListener* listener) {
internal_->SetAdListener(listener);
}

const NativeAdImage& NativeAd::icon() const { return internal_->icon(); }

const std::vector<NativeAdImage>& NativeAd::images() const {
Expand Down
35 changes: 34 additions & 1 deletion gma/src/common/native_ad_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace gma {
namespace internal {

NativeAdInternal::NativeAdInternal(NativeAd* base)
: base_(base), future_data_(kNativeAdFnCount) {}
: base_(base), future_data_(kNativeAdFnCount), ad_listener_(nullptr) {}

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

void NativeAdInternal::SetAdListener(AdListener* listener) {
MutexLock lock(listener_mutex_);
ad_listener_ = listener;
}

void NativeAdInternal::NotifyListenerAdClicked() {
MutexLock lock(listener_mutex_);
if (ad_listener_ != nullptr) {
ad_listener_->OnAdClicked();
}
}

void NativeAdInternal::NotifyListenerAdClosed() {
MutexLock lock(listener_mutex_);
if (ad_listener_ != nullptr) {
ad_listener_->OnAdClosed();
}
}

void NativeAdInternal::NotifyListenerAdImpression() {
MutexLock lock(listener_mutex_);
if (ad_listener_ != nullptr) {
ad_listener_->OnAdImpression();
}
}

void NativeAdInternal::NotifyListenerAdOpened() {
MutexLock lock(listener_mutex_);
if (ad_listener_ != nullptr) {
ad_listener_->OnAdOpened();
}
}

void NativeAdInternal::insert_image(const NativeAdImage& image,
const std::string& image_type) {
if (image_type == "icon") {
Expand Down
15 changes: 15 additions & 0 deletions gma/src/common/native_ad_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ class NativeAdInternal {
// Retrieves the most recent AdResult future for the LoadAd function.
Future<AdResult> GetLoadAdLastResult();

// Sets an AdListener for this ad view.
virtual void SetAdListener(AdListener* listener);

// Notifies the Ad listener (if one exists) that an event has occurred.
void NotifyListenerAdClicked();
void NotifyListenerAdClosed();
void NotifyListenerAdImpression();
void NotifyListenerAdOpened();

// Returns true if the NativeAd has been initialized.
virtual bool is_initialized() const = 0;

Expand Down Expand Up @@ -101,6 +110,9 @@ class NativeAdInternal {
// Future data used to synchronize asynchronous calls.
FutureData future_data_;

// Listener for NativeAd Lifecycle event callbacks.
AdListener* ad_listener_;

// Tracks the native ad icon asset.
NativeAdImage icon_;

Expand All @@ -109,6 +121,9 @@ class NativeAdInternal {

// Tracks the native ad choices icon asset.
NativeAdImage adchoices_icon_;

// Lock object for accessing ad_listener_.
Mutex listener_mutex_;
};

} // namespace internal
Expand Down
6 changes: 6 additions & 0 deletions gma/src/include/firebase/gma/internal/native_ad.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ class NativeAd {
/// LoadAd.
Future<AdResult> LoadAdLastResult() const;

/// Sets an AdListener for this native ad.
///
/// @param[in] listener An AdListener object which will be invoked
/// when lifecycle events occur on this NativeAd.
void SetAdListener(AdListener* listener);

/// Returns the associated icon asset of the native ad.
const NativeAdImage& icon() const;

Expand Down
18 changes: 18 additions & 0 deletions gma/src/ios/FADNativeDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,22 @@ - (void)adLoader:(GADAdLoader *)adLoader didReceiveNativeAd:(GADNativeAd *)nativ
_nativeAd->NativeAdDidReceiveAd(nativeAd);
}

#pragma mark GADNativeAdDelegate implementation

- (void)nativeAdDidRecordClick:(nonnull GADNativeAd *)nativeAd {
_nativeAd->NotifyListenerAdClicked();
}

- (void)nativeAdDidRecordImpression:(nonnull GADNativeAd *)nativeAd {
_nativeAd->NotifyListenerAdImpression();
}

- (void)nativeAdWillPresentScreen:(nonnull GADNativeAd *)nativeAd {
_nativeAd->NotifyListenerAdOpened();
}

- (void)nativeAdDidDismissScreen:(nonnull GADNativeAd *)nativeAd {
_nativeAd->NotifyListenerAdClosed();
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void run() {
});
}

/** Disconnect the helper from the interstital ad. */
/** Disconnect the helper from the native ad. */
public void disconnect() {
synchronized (mNativeLock) {
mNativeAdInternalPtr = CPP_NULLPTR;
Expand Down Expand Up @@ -263,6 +263,42 @@ public void onNativeAdLoaded(NativeAd ad) {
}
}
}

@Override
public void onAdClicked() {
synchronized (mNativeLock) {
if (mNativeAdInternalPtr != CPP_NULLPTR) {
notifyAdClicked(mNativeAdInternalPtr);
}
}
}

@Override
public void onAdImpression() {
synchronized (mNativeLock) {
if (mNativeAdInternalPtr != CPP_NULLPTR) {
notifyAdImpression(mNativeAdInternalPtr);
}
}
}

@Override
public void onAdClosed() {
synchronized (mNativeLock) {
if (mNativeAdInternalPtr != CPP_NULLPTR) {
notifyAdClosed(mNativeAdInternalPtr);
}
}
}

@Override
public void onAdOpened() {
synchronized (mNativeLock) {
if (mNativeAdInternalPtr != CPP_NULLPTR) {
notifyAdOpened(mNativeAdInternalPtr);
}
}
}
}

/** Native callback to instruct the C++ wrapper to complete the corresponding future. */
Expand All @@ -287,4 +323,16 @@ public static native void completeNativeLoadAdError(
*/
public static native void completeNativeLoadAdInternalError(
long nativeInternalPtr, int gmaErrorCode, String errorMessage);

/** Native callback to notify the C++ wrapper of an ad clicked event */
public static native void notifyAdClicked(long nativeInternalPtr);

/** Native callback to notify the C++ wrapper of an ad closed event */
public static native void notifyAdClosed(long nativeInternalPtr);

/** Native callback to notify the C++ wrapper of an ad impression event */
public static native void notifyAdImpression(long nativeInternalPtr);

/** Native callback to notify the C++ wrapper of an ad opened event */
public static native void notifyAdOpened(long nativeInternalPtr);
}
Loading