diff --git a/README.md b/README.md index efa3f55e..f7e412b5 100644 --- a/README.md +++ b/README.md @@ -127,9 +127,9 @@ When using The New Architecture, some legacy code will still be used though. See | iOS | User Messaging Platform (Turbo Native Module) | ✅ Complete | | iOS | [EventEmitter](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/turbo-modules.md#add-event-emitting-capabilities) (Turbo Native Module) | ⏳ To-Do | | iOS | Revenue Precision Constants (Turbo Native Module) | ✅ Complete | -| Android | Mobile Ads SDK Methods (Turbo Native Module) | ⏳ To-Do | -| Android | Banners (Fabric Native Component) | ⏳ To-Do | -| Android | Full Screen Ads (Turbo Native Module) | ⏳ To-Do | +| Android | Mobile Ads SDK Methods (Turbo Native Module) | ✅ Complete | +| Android | Banners (Fabric Native Component) | ✅ Complete | +| Android | Full Screen Ads (Turbo Native Module) | ✅ Complete | | Android | Native Ads (Turbo Native Module, Fabric Native Component) | ✅ Complete | | Android | User Messaging Platform (Turbo Native Module) | ⏳ To-Do | | Android | [EventEmitter](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/turbo-modules.md#add-event-emitting-capabilities) (Turbo Native Module) | ⏳ To-Do | diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeAppModule.java b/android/src/main/java/io/invertase/googlemobileads/ReactNativeAppModule.java index ef810132..4b60fc3b 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeAppModule.java +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeAppModule.java @@ -17,8 +17,11 @@ * */ +import androidx.annotation.NonNull; + import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; import io.invertase.googlemobileads.common.RCTConvert; @@ -26,20 +29,27 @@ import io.invertase.googlemobileads.common.ReactNativeEventEmitter; import io.invertase.googlemobileads.common.ReactNativeJSON; import io.invertase.googlemobileads.common.ReactNativeMeta; -import io.invertase.googlemobileads.common.ReactNativeModule; import io.invertase.googlemobileads.common.ReactNativePreferences; -public class ReactNativeAppModule extends ReactNativeModule { +public class ReactNativeAppModule extends ReactContextBaseJavaModule { static final String NAME = "RNAppModule"; + ReactApplicationContext context; ReactNativeAppModule(ReactApplicationContext reactContext) { - super(reactContext, NAME); + super(reactContext); + context=reactContext; + } + + @NonNull + @Override + public String getName() { + return NAME; } @Override public void initialize() { super.initialize(); - ReactNativeEventEmitter.getSharedInstance().attachReactContext(getContext()); + ReactNativeEventEmitter.getSharedInstance().attachReactContext(context); } @ReactMethod diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModule.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModule.kt index 9f412b85..cc448f43 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModule.kt +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModule.kt @@ -1,73 +1,34 @@ package io.invertase.googlemobileads -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import android.app.Activity +import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReadableMap -import com.google.android.gms.ads.AdLoadCallback -import com.google.android.gms.ads.LoadAdError -import com.google.android.gms.ads.admanager.AdManagerAdRequest -import com.google.android.gms.ads.appopen.AppOpenAd class ReactNativeGoogleMobileAdsAppOpenModule(reactContext: ReactApplicationContext?) : - ReactNativeGoogleMobileAdsFullScreenAdModule(reactContext, NAME) { + NativeAppOpenModuleSpec(reactContext) { - override fun getAdEventName(): String { - return ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_APP_OPEN - } + private var instance: ReactNativeGoogleMobileAdsAppOpenModuleImpl = + ReactNativeGoogleMobileAdsAppOpenModuleImpl(reactContext) - @ReactMethod - fun appOpenLoad(requestId: Int, adUnitId: String, adRequestOptions: ReadableMap) { - load(requestId, adUnitId, adRequestOptions) - } - - @ReactMethod - fun appOpenShow( - requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise + override fun appOpenLoad( + requestId: Double, + adUnitId: String, + requestOptions: ReadableMap? ) { - show(requestId, adUnitId, showOptions, promise) + instance.appOpenLoad(requestId.toInt(), adUnitId, requestOptions ?: Arguments.createMap()) } - override fun loadAd( - activity: Activity, + override fun appOpenShow( + requestId: Double, adUnitId: String, - adRequest: AdManagerAdRequest, - adLoadCallback: AdLoadCallback + showOptions: ReadableMap?, + promise: Promise ) { - AppOpenAd.load( - activity, - adUnitId, - adRequest, - object : - AppOpenAd.AppOpenAdLoadCallback() { - override fun onAdLoaded(ad: AppOpenAd) { - adLoadCallback.onAdLoaded(ad) - } - override fun onAdFailedToLoad(error: LoadAdError) { - adLoadCallback.onAdFailedToLoad(error) - } - }) + instance.appOpenShow(requestId.toInt(), adUnitId, showOptions ?: Arguments.createMap(), promise) } companion object { - const val NAME = "RNGoogleMobileAdsAppOpenModule" + const val NAME = NativeAppOpenModuleSpec.NAME } } diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModuleImpl.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModuleImpl.kt new file mode 100644 index 00000000..2d62d161 --- /dev/null +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModuleImpl.kt @@ -0,0 +1,67 @@ +package io.invertase.googlemobileads + +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import android.app.Activity +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReadableMap +import com.google.android.gms.ads.AdLoadCallback +import com.google.android.gms.ads.LoadAdError +import com.google.android.gms.ads.admanager.AdManagerAdRequest +import com.google.android.gms.ads.appopen.AppOpenAd + +class ReactNativeGoogleMobileAdsAppOpenModuleImpl(reactContext: ReactApplicationContext?) : + ReactNativeGoogleMobileAdsFullScreenAdModule(reactContext) { + + override fun getAdEventName(): String { + return ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_APP_OPEN + } + + fun appOpenLoad(requestId: Int, adUnitId: String, adRequestOptions: ReadableMap) { + load(requestId, adUnitId, adRequestOptions) + } + + fun appOpenShow( + requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise + ) { + show(requestId, adUnitId, showOptions, promise) + } + + override fun loadAd( + activity: Activity, + adUnitId: String, + adRequest: AdManagerAdRequest, + adLoadCallback: AdLoadCallback + ) { + AppOpenAd.load( + activity, + adUnitId, + adRequest, + object : + AppOpenAd.AppOpenAdLoadCallback() { + override fun onAdLoaded(ad: AppOpenAd) { + adLoadCallback.onAdLoaded(ad) + } + + override fun onAdFailedToLoad(error: LoadAdError) { + adLoadCallback.onAdFailedToLoad(error) + } + }) + } +} diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsBannerAdViewManager.java b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsBannerAdViewManager.java index 56712602..140f042e 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsBannerAdViewManager.java +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsBannerAdViewManager.java @@ -19,7 +19,9 @@ import android.app.Activity; import android.view.ViewGroup; + import androidx.annotation.NonNull; + import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; @@ -31,8 +33,11 @@ import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.UIManagerHelper; +import com.facebook.react.uimanager.ViewManagerDelegate; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.viewmanagers.RNGoogleMobileAdsBannerViewManagerInterface; +import com.facebook.react.viewmanagers.RNGoogleMobileAdsBannerViewManagerDelegate; import com.google.android.gms.ads.AdListener; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.AdSize; @@ -43,18 +48,22 @@ import com.google.android.gms.ads.OnPaidEventListener; import com.google.android.gms.ads.admanager.AdManagerAdView; import com.google.android.gms.ads.admanager.AppEventListener; + import io.invertase.googlemobileads.common.ReactNativeAdView; import io.invertase.googlemobileads.common.SharedUtils; + import java.util.ArrayList; import java.util.List; import java.util.Map; + import javax.annotation.Nonnull; import javax.annotation.Nullable; + import org.json.JSONException; import org.json.JSONObject; public class ReactNativeGoogleMobileAdsBannerAdViewManager - extends SimpleViewManager { + extends SimpleViewManager implements RNGoogleMobileAdsBannerViewManagerInterface { private static final String REACT_CLASS = "RNGoogleMobileAdsBannerView"; private final String EVENT_AD_LOADED = "onAdLoaded"; private final String EVENT_AD_IMPRESSION = "onAdImpression"; @@ -65,8 +74,7 @@ public class ReactNativeGoogleMobileAdsBannerAdViewManager private final String EVENT_PAID = "onPaid"; private final String EVENT_SIZE_CHANGE = "onSizeChange"; private final String EVENT_APP_EVENT = "onAppEvent"; - private final String COMMAND_ID_RECORD_MANUAL_IMPRESSION = "recordManualImpression"; - private final String COMMAND_ID_LOAD = "load"; + private final ViewManagerDelegate delegate = new RNGoogleMobileAdsBannerViewManagerDelegate<>(this); @Nonnull @Override @@ -74,6 +82,12 @@ public String getName() { return REACT_CLASS; } + @androidx.annotation.Nullable + @Override + protected ViewManagerDelegate getDelegate() { + return delegate; + } + @Nonnull @Override public ReactNativeAdView createViewInstance(@Nonnull ThemedReactContext themedReactContext) { @@ -87,23 +101,6 @@ public Map getExportedCustomDirectEventTypeConstants() { return builder.build(); } - @Override - public void receiveCommand( - @NonNull ReactNativeAdView reactViewGroup, String commandId, @Nullable ReadableArray args) { - super.receiveCommand(reactViewGroup, commandId, args); - - if (commandId.equals(COMMAND_ID_RECORD_MANUAL_IMPRESSION)) { - BaseAdView adView = getAdView(reactViewGroup); - if (adView instanceof AdManagerAdView) { - ((AdManagerAdView) adView).recordManualImpression(); - } - } else if (commandId.equals(COMMAND_ID_LOAD)) { - BaseAdView adView = getAdView(reactViewGroup); - AdRequest request = reactViewGroup.getRequest(); - adView.loadAd(request); - } - } - @ReactProp(name = "unitId") public void setUnitId(ReactNativeAdView reactViewGroup, String value) { reactViewGroup.setUnitId(value); @@ -150,7 +147,7 @@ public void setSizeConfig(ReactNativeAdView reactViewGroup, ReadableMap sizeConf if (sizesArray.getType(i) == ReadableType.String) { String sizeString = sizesArray.getString(i); AdSize adSize = - ReactNativeGoogleMobileAdsCommon.getAdSize(sizeString, reactViewGroup); + ReactNativeGoogleMobileAdsCommon.getAdSize(sizeString, reactViewGroup); sizeList.add(adSize); } } @@ -178,6 +175,23 @@ public void setManualImpressionsEnabled(ReactNativeAdView reactViewGroup, boolea reactViewGroup.setPropsChanged(true); } + @Override + public void recordManualImpression(ReactNativeAdView view) { + BaseAdView adView = getAdView(view); + if (adView instanceof AdManagerAdView) { + ((AdManagerAdView) adView).recordManualImpression(); + } + } + + @Override + public void load(ReactNativeAdView view) { + BaseAdView adView = getAdView(view); + AdRequest request = view.getRequest(); + if (adView != null) { + adView.loadAd(request); + } + } + @Override public void onAfterUpdateTransaction(@NonNull ReactNativeAdView reactViewGroup) { super.onAfterUpdateTransaction(reactViewGroup); @@ -219,95 +233,95 @@ private BaseAdView initAdView(ReactNativeAdView reactViewGroup) { if (currentActivity == null) return null; BaseAdView adView = - ReactNativeGoogleMobileAdsCommon.isAdManagerUnit(reactViewGroup.getUnitId()) - ? new AdManagerAdView(currentActivity) - : new AdView(currentActivity); + ReactNativeGoogleMobileAdsCommon.isAdManagerUnit(reactViewGroup.getUnitId()) + ? new AdManagerAdView(currentActivity) + : new AdView(currentActivity); adView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); adView.setOnPaidEventListener( - new OnPaidEventListener() { - @Override - public void onPaidEvent(AdValue adValue) { - WritableMap payload = Arguments.createMap(); - payload.putDouble("value", 1e-6 * adValue.getValueMicros()); - payload.putDouble("precision", adValue.getPrecisionType()); - payload.putString("currency", adValue.getCurrencyCode()); - sendEvent(reactViewGroup, EVENT_PAID, payload); - } - }); + new OnPaidEventListener() { + @Override + public void onPaidEvent(AdValue adValue) { + WritableMap payload = Arguments.createMap(); + payload.putDouble("value", 1e-6 * adValue.getValueMicros()); + payload.putDouble("precision", adValue.getPrecisionType()); + payload.putString("currency", adValue.getCurrencyCode()); + sendEvent(reactViewGroup, EVENT_PAID, payload); + } + }); adView.setAdListener( - new AdListener() { - @Override - public void onAdLoaded() { - AdSize adSize = adView.getAdSize(); - int width, height; - if (reactViewGroup.getIsFluid()) { - width = reactViewGroup.getWidth(); - height = reactViewGroup.getHeight(); - - adView.addOnLayoutChangeListener( - (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { - WritableMap payload = Arguments.createMap(); - payload.putDouble("width", PixelUtil.toDIPFromPixel(right - left)); - payload.putDouble("height", PixelUtil.toDIPFromPixel(bottom - top)); - sendEvent(reactViewGroup, EVENT_SIZE_CHANGE, payload); - }); - } else { - int left = adView.getLeft(); - int top = adView.getTop(); - width = adSize.getWidthInPixels(reactViewGroup.getContext()); - height = adSize.getHeightInPixels(reactViewGroup.getContext()); - - adView.measure(width, height); - adView.layout(left, top, left + width, top + height); - } + new AdListener() { + @Override + public void onAdLoaded() { + AdSize adSize = adView.getAdSize(); + int width, height; + if (reactViewGroup.getIsFluid()) { + width = reactViewGroup.getWidth(); + height = reactViewGroup.getHeight(); + + adView.addOnLayoutChangeListener( + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + WritableMap payload = Arguments.createMap(); + payload.putDouble("width", PixelUtil.toDIPFromPixel(right - left)); + payload.putDouble("height", PixelUtil.toDIPFromPixel(bottom - top)); + sendEvent(reactViewGroup, EVENT_SIZE_CHANGE, payload); + }); + } else { + int left = adView.getLeft(); + int top = adView.getTop(); + width = adSize.getWidthInPixels(reactViewGroup.getContext()); + height = adSize.getHeightInPixels(reactViewGroup.getContext()); + + adView.measure(width, height); + adView.layout(left, top, left + width, top + height); + } - WritableMap payload = Arguments.createMap(); - payload.putDouble("width", PixelUtil.toDIPFromPixel(width)); - payload.putDouble("height", PixelUtil.toDIPFromPixel(height)); + WritableMap payload = Arguments.createMap(); + payload.putDouble("width", PixelUtil.toDIPFromPixel(width)); + payload.putDouble("height", PixelUtil.toDIPFromPixel(height)); - sendEvent(reactViewGroup, EVENT_AD_LOADED, payload); - } + sendEvent(reactViewGroup, EVENT_AD_LOADED, payload); + } - @Override - public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) { - int errorCode = loadAdError.getCode(); - WritableMap payload = ReactNativeGoogleMobileAdsCommon.errorCodeToMap(errorCode); - sendEvent(reactViewGroup, EVENT_AD_FAILED_TO_LOAD, payload); - } + @Override + public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) { + int errorCode = loadAdError.getCode(); + WritableMap payload = ReactNativeGoogleMobileAdsCommon.errorCodeToMap(errorCode); + sendEvent(reactViewGroup, EVENT_AD_FAILED_TO_LOAD, payload); + } - @Override - public void onAdOpened() { - sendEvent(reactViewGroup, EVENT_AD_OPENED, null); - } + @Override + public void onAdOpened() { + sendEvent(reactViewGroup, EVENT_AD_OPENED, null); + } - @Override - public void onAdClosed() { - sendEvent(reactViewGroup, EVENT_AD_CLOSED, null); - } + @Override + public void onAdClosed() { + sendEvent(reactViewGroup, EVENT_AD_CLOSED, null); + } - @Override - public void onAdImpression() { - sendEvent(reactViewGroup, EVENT_AD_IMPRESSION, null); - } + @Override + public void onAdImpression() { + sendEvent(reactViewGroup, EVENT_AD_IMPRESSION, null); + } - @Override - public void onAdClicked() { - sendEvent(reactViewGroup, EVENT_AD_CLICKED, null); - } - }); + @Override + public void onAdClicked() { + sendEvent(reactViewGroup, EVENT_AD_CLICKED, null); + } + }); if (adView instanceof AdManagerAdView) { ((AdManagerAdView) adView) - .setAppEventListener( - new AppEventListener() { - @Override - public void onAppEvent(@NonNull String name, @Nullable String data) { - WritableMap payload = Arguments.createMap(); - payload.putString("name", name); - payload.putString("data", data); - sendEvent(reactViewGroup, EVENT_APP_EVENT, payload); - } - }); + .setAppEventListener( + new AppEventListener() { + @Override + public void onAppEvent(@NonNull String name, @Nullable String data) { + WritableMap payload = Arguments.createMap(); + payload.putString("name", name); + payload.putString("data", data); + sendEvent(reactViewGroup, EVENT_APP_EVENT, payload); + } + }); } reactViewGroup.addView(adView); return adView; @@ -359,7 +373,7 @@ private void sendEvent(ReactNativeAdView reactViewGroup, String type, WritableMa ThemedReactContext themedReactContext = ((ThemedReactContext) reactViewGroup.getContext()); EventDispatcher eventDispatcher = - UIManagerHelper.getEventDispatcherForReactTag(themedReactContext, reactViewGroup.getId()); + UIManagerHelper.getEventDispatcherForReactTag(themedReactContext, reactViewGroup.getId()); if (eventDispatcher != null) { eventDispatcher.dispatchEvent(new OnNativeEvent(reactViewGroup.getId(), event)); } diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsConsentModule.java b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsConsentModule.java index aa81b097..77486055 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsConsentModule.java +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsConsentModule.java @@ -16,9 +16,11 @@ * limitations under the License. * */ + import android.app.Activity; import android.content.SharedPreferences; import android.preference.PreferenceManager; + import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; @@ -30,16 +32,16 @@ import com.google.android.ump.ConsentInformation; import com.google.android.ump.ConsentRequestParameters; import com.google.android.ump.UserMessagingPlatform; -import io.invertase.googlemobileads.common.ReactNativeModule; -import javax.annotation.Nonnull; -public class ReactNativeGoogleMobileAdsConsentModule extends ReactNativeModule { +import javax.annotation.Nonnull; - static final String NAME = "RNGoogleMobileAdsConsentModule"; +public class ReactNativeGoogleMobileAdsConsentModule extends NativeConsentModuleSpec { private ConsentInformation consentInformation; + private ReactApplicationContext context; public ReactNativeGoogleMobileAdsConsentModule(ReactApplicationContext reactContext) { - super(reactContext, NAME); + super(reactContext); + context = reactContext; consentInformation = UserMessagingPlatform.getConsentInformation(reactContext); } @@ -58,7 +60,7 @@ private String getConsentStatusString(int consentStatus) { } private String getPrivacyOptionsRequirementStatusString( - ConsentInformation.PrivacyOptionsRequirementStatus privacyOptionsRequirementStatus) { + ConsentInformation.PrivacyOptionsRequirementStatus privacyOptionsRequirementStatus) { switch (privacyOptionsRequirementStatus) { case REQUIRED: return "REQUIRED"; @@ -73,14 +75,14 @@ private String getPrivacyOptionsRequirementStatusString( private WritableMap getConsentInformation() { WritableMap consentStatusMap = Arguments.createMap(); consentStatusMap.putString( - "status", getConsentStatusString(consentInformation.getConsentStatus())); + "status", getConsentStatusString(consentInformation.getConsentStatus())); consentStatusMap.putBoolean("canRequestAds", consentInformation.canRequestAds()); consentStatusMap.putString( - "privacyOptionsRequirementStatus", - getPrivacyOptionsRequirementStatusString( - consentInformation.getPrivacyOptionsRequirementStatus())); + "privacyOptionsRequirementStatus", + getPrivacyOptionsRequirementStatusString( + consentInformation.getPrivacyOptionsRequirementStatus())); consentStatusMap.putBoolean( - "isConsentFormAvailable", consentInformation.isConsentFormAvailable()); + "isConsentFormAvailable", consentInformation.isConsentFormAvailable()); return consentStatusMap; } @@ -89,7 +91,7 @@ public void requestInfoUpdate(@Nonnull final ReadableMap options, final Promise try { ConsentRequestParameters.Builder paramsBuilder = new ConsentRequestParameters.Builder(); ConsentDebugSettings.Builder debugSettingsBuilder = - new ConsentDebugSettings.Builder(getApplicationContext()); + new ConsentDebugSettings.Builder(context.getApplicationContext()); if (options.hasKey("testDeviceIdentifiers")) { ReadableArray devices = options.getArray("testDeviceIdentifiers"); @@ -115,21 +117,21 @@ public void requestInfoUpdate(@Nonnull final ReadableMap options, final Promise if (currentActivity == null) { rejectPromiseWithCodeAndMessage( - promise, - "null-activity", - "Attempted to request a consent info update but the current Activity was null."); + promise, + "null-activity", + "Attempted to request a consent info update but the current Activity was null."); return; } consentInformation.requestConsentInfoUpdate( - currentActivity, - consentRequestParameters, - () -> { - promise.resolve(getConsentInformation()); - }, - formError -> - rejectPromiseWithCodeAndMessage( - promise, "consent-update-failed", formError.getMessage())); + currentActivity, + consentRequestParameters, + () -> { + promise.resolve(getConsentInformation()); + }, + formError -> + rejectPromiseWithCodeAndMessage( + promise, "consent-update-failed", formError.getMessage())); } catch (Exception e) { rejectPromiseWithCodeAndMessage(promise, "consent-update-failed", e.toString()); } @@ -142,30 +144,30 @@ public void showForm(final Promise promise) { if (currentActivity == null) { rejectPromiseWithCodeAndMessage( - promise, - "null-activity", - "Consent form attempted to show but the current Activity was null."); + promise, + "null-activity", + "Consent form attempted to show but the current Activity was null."); return; } currentActivity.runOnUiThread( - () -> - UserMessagingPlatform.loadConsentForm( - getReactApplicationContext(), - consentForm -> - consentForm.show( - currentActivity, - formError -> { - if (formError != null) { - rejectPromiseWithCodeAndMessage( - promise, "consent-form-error", formError.getMessage()); - } else { - promise.resolve(getConsentInformation()); - } - }), - formError -> - rejectPromiseWithCodeAndMessage( - promise, "consent-form-error", formError.getMessage()))); + () -> + UserMessagingPlatform.loadConsentForm( + getReactApplicationContext(), + consentForm -> + consentForm.show( + currentActivity, + formError -> { + if (formError != null) { + rejectPromiseWithCodeAndMessage( + promise, "consent-form-error", formError.getMessage()); + } else { + promise.resolve(getConsentInformation()); + } + }), + formError -> + rejectPromiseWithCodeAndMessage( + promise, "consent-form-error", formError.getMessage()))); } catch (Exception e) { rejectPromiseWithCodeAndMessage(promise, "consent-form-error", e.toString()); } @@ -178,24 +180,24 @@ public void showPrivacyOptionsForm(final Promise promise) { if (currentActivity == null) { rejectPromiseWithCodeAndMessage( - promise, - "null-activity", - "Privacy options form attempted to show but the current Activity was null."); + promise, + "null-activity", + "Privacy options form attempted to show but the current Activity was null."); return; } currentActivity.runOnUiThread( - () -> - UserMessagingPlatform.showPrivacyOptionsForm( - currentActivity, - formError -> { - if (formError != null) { - rejectPromiseWithCodeAndMessage( - promise, "privacy-options-form-error", formError.getMessage()); - } else { - promise.resolve(getConsentInformation()); - } - })); + () -> + UserMessagingPlatform.showPrivacyOptionsForm( + currentActivity, + formError -> { + if (formError != null) { + rejectPromiseWithCodeAndMessage( + promise, "privacy-options-form-error", formError.getMessage()); + } else { + promise.resolve(getConsentInformation()); + } + })); } catch (Exception e) { rejectPromiseWithCodeAndMessage(promise, "consent-form-error", e.toString()); } @@ -208,25 +210,25 @@ public void loadAndShowConsentFormIfRequired(final Promise promise) { if (currentActivity == null) { rejectPromiseWithCodeAndMessage( - promise, - "null-activity", - "Consent form attempted to load and show if required but the current Activity was" - + " null."); + promise, + "null-activity", + "Consent form attempted to load and show if required but the current Activity was" + + " null."); return; } currentActivity.runOnUiThread( - () -> - UserMessagingPlatform.loadAndShowConsentFormIfRequired( - currentActivity, - formError -> { - if (formError != null) { - rejectPromiseWithCodeAndMessage( - promise, "consent-form-error", formError.getMessage()); - } else { - promise.resolve(getConsentInformation()); - } - })); + () -> + UserMessagingPlatform.loadAndShowConsentFormIfRequired( + currentActivity, + formError -> { + if (formError != null) { + rejectPromiseWithCodeAndMessage( + promise, "consent-form-error", formError.getMessage()); + } else { + promise.resolve(getConsentInformation()); + } + })); } catch (Exception e) { rejectPromiseWithCodeAndMessage(promise, "consent-form-error", e.toString()); } @@ -246,7 +248,7 @@ public void reset() { public void getTCString(Promise promise) { try { SharedPreferences prefs = - PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); + PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); // https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details String tcString = prefs.getString("IABTCF_TCString", null); promise.resolve(tcString); @@ -259,7 +261,7 @@ public void getTCString(Promise promise) { public void getGdprApplies(Promise promise) { try { SharedPreferences prefs = - PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); + PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); int gdprApplies = prefs.getInt("IABTCF_gdprApplies", 0); promise.resolve(gdprApplies == 1); } catch (Exception e) { @@ -271,7 +273,7 @@ public void getGdprApplies(Promise promise) { public void getPurposeConsents(Promise promise) { try { SharedPreferences prefs = - PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); + PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); String purposeConsents = prefs.getString("IABTCF_PurposeConsents", ""); promise.resolve(purposeConsents); } catch (Exception e) { @@ -283,11 +285,18 @@ public void getPurposeConsents(Promise promise) { public void getPurposeLegitimateInterests(Promise promise) { try { SharedPreferences prefs = - PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); + PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); String purposeLegitimateInterests = prefs.getString("IABTCF_PurposeLegitimateInterests", ""); promise.resolve(purposeLegitimateInterests); } catch (Exception e) { rejectPromiseWithCodeAndMessage(promise, "consent-string-error", e.toString()); } } + + public static void rejectPromiseWithCodeAndMessage(Promise promise, String code, String message) { + WritableMap userInfoMap = Arguments.createMap(); + userInfoMap.putString("code", code); + userInfoMap.putString("message", message); + promise.reject(code, message, userInfoMap); + } } diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsFullScreenAdModule.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsFullScreenAdModule.kt index 75cd58f9..6a836932 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsFullScreenAdModule.kt +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsFullScreenAdModule.kt @@ -36,8 +36,7 @@ import io.invertase.googlemobileads.common.ReactNativeModule abstract class ReactNativeGoogleMobileAdsFullScreenAdModule( reactContext: ReactApplicationContext?, - moduleName: String -) : ReactNativeModule(reactContext, moduleName) { +) : ReactNativeModule(reactContext) { private val adArray = SparseArray() abstract fun getAdEventName(): String @@ -69,7 +68,7 @@ abstract class ReactNativeGoogleMobileAdsFullScreenAdModule( fun load( requestId: Int, adUnitId: String, adRequestOptions: ReadableMap ) { - val activity = currentActivity + val activity = activity if (activity == null) { val error = Arguments.createMap() error.putString("code", "null-activity") @@ -105,7 +104,7 @@ abstract class ReactNativeGoogleMobileAdsFullScreenAdModule( fun show( requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise ) { - val activity = currentActivity + val activity = activity if (activity == null) { rejectPromiseWithCodeAndMessage( promise, @@ -251,8 +250,8 @@ abstract class ReactNativeGoogleMobileAdsFullScreenAdModule( data ) } catch (e: Exception) { - Log.w("RNGoogleMobileAds", "Unknown error on load") - Log.w("RNGoogleMobileAds", e) + Log.w("RNGoogleMobileAds", "Unknown error on load") + Log.w("RNGoogleMobileAds", e) val error = Arguments.createMap() error.putString("code", "internal") error.putString("message", e.message) diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModule.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModule.kt index 079ecb9b..43254516 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModule.kt +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModule.kt @@ -1,74 +1,40 @@ package io.invertase.googlemobileads -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import android.app.Activity +import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReadableMap -import com.google.android.gms.ads.AdLoadCallback -import com.google.android.gms.ads.LoadAdError -import com.google.android.gms.ads.admanager.AdManagerAdRequest import com.google.android.gms.ads.admanager.AdManagerInterstitialAd -import com.google.android.gms.ads.admanager.AdManagerInterstitialAdLoadCallback class ReactNativeGoogleMobileAdsInterstitialModule(reactContext: ReactApplicationContext?) : - ReactNativeGoogleMobileAdsFullScreenAdModule(reactContext, NAME) { + NativeInterstitialModuleSpec(reactContext) { - override fun getAdEventName(): String { - return ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_INTERSTITIAL - } + private val instance: ReactNativeGoogleMobileAdsInterstitialModuleImpl = + ReactNativeGoogleMobileAdsInterstitialModuleImpl(reactContext) - @ReactMethod - fun interstitialLoad(requestId: Int, adUnitId: String, adRequestOptions: ReadableMap) { - load(requestId, adUnitId, adRequestOptions) - } - - @ReactMethod - fun interstitialShow( - requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise + override fun interstitialLoad( + requestId: Double, + adUnitId: String, + requestOptions: ReadableMap? ) { - show(requestId, adUnitId, showOptions, promise) + instance.interstitialLoad(requestId.toInt(), adUnitId, requestOptions ?: Arguments.createMap()) } - override fun loadAd( - activity: Activity, + override fun interstitialShow( + requestId: Double, adUnitId: String, - adRequest: AdManagerAdRequest, - adLoadCallback: AdLoadCallback + showOptions: ReadableMap?, + promise: Promise ) { - AdManagerInterstitialAd.load( - activity, + instance.interstitialShow( + requestId.toInt(), adUnitId, - adRequest, - object : - AdManagerInterstitialAdLoadCallback() { - override fun onAdLoaded(ad: AdManagerInterstitialAd) { - adLoadCallback.onAdLoaded(ad) - } - override fun onAdFailedToLoad(error: LoadAdError) { - adLoadCallback.onAdFailedToLoad(error) - } - }) + showOptions ?: Arguments.createMap(), + promise + ) } companion object { - const val NAME = "RNGoogleMobileAdsInterstitialModule" + const val NAME = NativeInterstitialModuleSpec.NAME } } diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModuleImpl.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModuleImpl.kt new file mode 100644 index 00000000..84d1b89a --- /dev/null +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModuleImpl.kt @@ -0,0 +1,67 @@ +package io.invertase.googlemobileads + +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import android.app.Activity +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReadableMap +import com.google.android.gms.ads.AdLoadCallback +import com.google.android.gms.ads.LoadAdError +import com.google.android.gms.ads.admanager.AdManagerAdRequest +import com.google.android.gms.ads.admanager.AdManagerInterstitialAd +import com.google.android.gms.ads.admanager.AdManagerInterstitialAdLoadCallback + +class ReactNativeGoogleMobileAdsInterstitialModuleImpl(reactContext: ReactApplicationContext?) : + ReactNativeGoogleMobileAdsFullScreenAdModule(reactContext) { + + override fun getAdEventName(): String { + return ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_INTERSTITIAL + } + + fun interstitialLoad(requestId: Int, adUnitId: String, adRequestOptions: ReadableMap) { + load(requestId, adUnitId, adRequestOptions) + } + + fun interstitialShow( + requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise + ) { + show(requestId, adUnitId, showOptions, promise) + } + + override fun loadAd( + activity: Activity, + adUnitId: String, + adRequest: AdManagerAdRequest, + adLoadCallback: AdLoadCallback + ) { + AdManagerInterstitialAd.load( + activity, + adUnitId, + adRequest, + object : + AdManagerInterstitialAdLoadCallback() { + override fun onAdLoaded(ad: AdManagerInterstitialAd) { + adLoadCallback.onAdLoaded(ad) + } + override fun onAdFailedToLoad(error: LoadAdError) { + adLoadCallback.onAdFailedToLoad(error) + } + }) + } +} diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsModule.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsModule.kt index f4095f16..4df91fd1 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsModule.kt +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsModule.kt @@ -28,7 +28,7 @@ import com.google.android.gms.ads.OnAdInspectorClosedListener class ReactNativeGoogleMobileAdsModule( reactContext: ReactApplicationContext -) : ReactContextBaseJavaModule(reactContext) { +) : NativeGoogleMobileAdsModuleSpec(reactContext) { override fun getName() = NAME @@ -38,7 +38,8 @@ class ReactNativeGoogleMobileAdsModule( val builder = RequestConfiguration.Builder() if (requestConfiguration.hasKey("testDeviceIdentifiers")) { - val devices = checkNotNull(requestConfiguration.getArray("testDeviceIdentifiers")).toArrayList() + val devices = + checkNotNull(requestConfiguration.getArray("testDeviceIdentifiers")).toArrayList() val testDeviceIds = devices.map { val id = it as String; if (id == "EMULATOR") { @@ -63,7 +64,8 @@ class ReactNativeGoogleMobileAdsModule( } if (requestConfiguration.hasKey("tagForChildDirectedTreatment")) { - val tagForChildDirectedTreatment = requestConfiguration.getBoolean("tagForChildDirectedTreatment") + val tagForChildDirectedTreatment = + requestConfiguration.getBoolean("tagForChildDirectedTreatment") builder.setTagForChildDirectedTreatment( if (tagForChildDirectedTreatment) { RequestConfiguration.TAG_FOR_CHILD_DIRECTED_TREATMENT_TRUE @@ -91,8 +93,7 @@ class ReactNativeGoogleMobileAdsModule( return builder.build() } - @ReactMethod - fun initialize(promise: Promise) { + override fun initialize(promise: Promise) { MobileAds.initialize( // in react-native, the Activity instance *may* go away, becoming null after initialize // it is not clear if that can happen here without an initialize necessarily following the Activity lifecycle @@ -113,20 +114,25 @@ class ReactNativeGoogleMobileAdsModule( }); } - @ReactMethod - fun setRequestConfiguration( - requestConfiguration: ReadableMap, + override fun setRequestConfiguration( + requestConfiguration: ReadableMap?, promise: Promise ) { - MobileAds.setRequestConfiguration(buildRequestConfiguration(requestConfiguration)) + MobileAds.setRequestConfiguration( + buildRequestConfiguration( + requestConfiguration ?: Arguments.createMap() + ) + ) promise.resolve(null) } - @ReactMethod - fun openAdInspector(promise: Promise) { + override fun openAdInspector(promise: Promise) { val activity = reactApplicationContext.currentActivity if (activity == null) { - promise.reject("null-activity", "Ad Inspector attempted to open but the current Activity was null.") + promise.reject( + "null-activity", + "Ad Inspector attempted to open but the current Activity was null." + ) return } activity.runOnUiThread { @@ -150,24 +156,21 @@ class ReactNativeGoogleMobileAdsModule( } } - @ReactMethod - fun openDebugMenu(adUnit: String) { + override fun openDebugMenu(adUnit: String) { reactApplicationContext.currentActivity?.runOnUiThread { MobileAds.openDebugMenu(reactApplicationContext.currentActivity!!, adUnit) } } - @ReactMethod - fun setAppVolume(volume: Float) { - MobileAds.setAppVolume(volume) + override fun setAppVolume(volume: Double) { + MobileAds.setAppVolume(volume.toFloat()) } - @ReactMethod - fun setAppMuted(muted: Boolean) { + override fun setAppMuted(muted: Boolean) { MobileAds.setAppMuted(muted) } companion object { - const val NAME = "RNGoogleMobileAdsModule" + const val NAME = NativeGoogleMobileAdsModuleSpec.NAME } } diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsNativeModule.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsNativeModule.kt index 6e70fdd7..c192b59f 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsNativeModule.kt +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsNativeModule.kt @@ -97,7 +97,10 @@ class ReactNativeGoogleMobileAdsNativeModule( return adHolders[responseId]?.nativeAd } - private inner class NativeAdHolder(private val adUnitId: String, private val requestOptions: ReadableMap) { + private inner class NativeAdHolder( + private val adUnitId: String, + private val requestOptions: ReadableMap + ) { var nativeAd: NativeAd? = null private set @@ -119,27 +122,30 @@ class ReactNativeGoogleMobileAdsNativeModule( } } - private val videoLifecycleCallbacks: VideoLifecycleCallbacks = object : VideoLifecycleCallbacks() { - override fun onVideoPlay() { - emitAdEvent("video_played") - } + private val videoLifecycleCallbacks: VideoLifecycleCallbacks = + object : VideoLifecycleCallbacks() { + override fun onVideoPlay() { + emitAdEvent("video_played") + } - override fun onVideoPause() { - emitAdEvent("video_paused") - } + override fun onVideoPause() { + emitAdEvent("video_paused") + } - override fun onVideoEnd() { - emitAdEvent("video_ended") - } + override fun onVideoEnd() { + emitAdEvent("video_ended") + } - override fun onVideoMute(isMuted: Boolean) { - emitAdEvent(if (isMuted) { - "video_muted" - } else { - "video_unmuted" - }) + override fun onVideoMute(isMuted: Boolean) { + emitAdEvent( + if (isMuted) { + "video_muted" + } else { + "video_unmuted" + } + ) + } } - } fun loadAd(loadedListener: NativeAd.OnNativeAdLoadedListener) { val mediaAspectRatio = if (requestOptions.hasKey("aspectRatio")) { @@ -216,6 +222,6 @@ class ReactNativeGoogleMobileAdsNativeModule( } companion object { - const val NAME = "RNGoogleMobileAdsNativeModule" + const val NAME = NativeGoogleMobileAdsNativeModuleSpec.NAME } } diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModule.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModule.kt index eabb5b71..3f757756 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModule.kt +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModule.kt @@ -1,74 +1,44 @@ package io.invertase.googlemobileads -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import android.app.Activity +import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReadableMap -import com.google.android.gms.ads.AdLoadCallback -import com.google.android.gms.ads.LoadAdError -import com.google.android.gms.ads.admanager.AdManagerAdRequest import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd -import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAdLoadCallback class ReactNativeGoogleMobileAdsRewardedInterstitialModule(reactContext: ReactApplicationContext?) : - ReactNativeGoogleMobileAdsFullScreenAdModule(reactContext, NAME) { - - override fun getAdEventName(): String { - return ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_REWARDED_INTERSTITIAL - } + NativeRewardedInterstitialModuleSpec(reactContext) { - @ReactMethod - fun rewardedInterstitialLoad(requestId: Int, adUnitId: String, adRequestOptions: ReadableMap) { - load(requestId, adUnitId, adRequestOptions) - } + private val instance: ReactNativeGoogleMobileAdsRewardedInterstitialModuleImpl = + ReactNativeGoogleMobileAdsRewardedInterstitialModuleImpl(reactContext) - @ReactMethod - fun rewardedInterstitialShow( - requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise + override fun rewardedInterstitialLoad( + requestId: Double, + adUnitId: String, + requestOptions: ReadableMap? ) { - show(requestId, adUnitId, showOptions, promise) + instance.rewardedInterstitialLoad( + requestId.toInt(), + adUnitId, + requestOptions ?: Arguments.createMap() + ) } - override fun loadAd( - activity: Activity, + override fun rewardedInterstitialShow( + requestId: Double, adUnitId: String, - adRequest: AdManagerAdRequest, - adLoadCallback: AdLoadCallback + showOptions: ReadableMap?, + promise: Promise ) { - RewardedInterstitialAd.load( - activity, + instance.rewardedInterstitialShow( + requestId.toInt(), adUnitId, - adRequest, - object : - RewardedInterstitialAdLoadCallback() { - override fun onAdLoaded(ad: RewardedInterstitialAd) { - adLoadCallback.onAdLoaded(ad) - } - override fun onAdFailedToLoad(error: LoadAdError) { - adLoadCallback.onAdFailedToLoad(error) - } - }) + showOptions ?: Arguments.createMap(), + promise + ) } companion object { - const val NAME = "RNGoogleMobileAdsRewardedInterstitialModule" + const val NAME = NativeRewardedInterstitialModuleSpec.NAME } } diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModuleImpl.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModuleImpl.kt new file mode 100644 index 00000000..9d64a400 --- /dev/null +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModuleImpl.kt @@ -0,0 +1,69 @@ +package io.invertase.googlemobileads + +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import android.app.Activity +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReadableMap +import com.google.android.gms.ads.AdLoadCallback +import com.google.android.gms.ads.LoadAdError +import com.google.android.gms.ads.admanager.AdManagerAdRequest +import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd +import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAdLoadCallback + +class ReactNativeGoogleMobileAdsRewardedInterstitialModuleImpl(reactContext: ReactApplicationContext?) : + ReactNativeGoogleMobileAdsFullScreenAdModule(reactContext) { + + override fun getAdEventName(): String { + return ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_REWARDED_INTERSTITIAL + } + + fun rewardedInterstitialLoad(requestId: Int, adUnitId: String, adRequestOptions: ReadableMap) { + load(requestId, adUnitId, adRequestOptions) + } + + fun rewardedInterstitialShow( + requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise + ) { + show(requestId, adUnitId, showOptions, promise) + } + + override fun loadAd( + activity: Activity, + adUnitId: String, + adRequest: AdManagerAdRequest, + adLoadCallback: AdLoadCallback + ) { + RewardedInterstitialAd.load( + activity, + adUnitId, + adRequest, + object : + RewardedInterstitialAdLoadCallback() { + override fun onAdLoaded(ad: RewardedInterstitialAd) { + adLoadCallback.onAdLoaded(ad) + } + + override fun onAdFailedToLoad(error: LoadAdError) { + adLoadCallback.onAdFailedToLoad(error) + } + }) + } + +} diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedModule.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedModule.kt index 7d1b980e..92edb7ac 100644 --- a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedModule.kt +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedModule.kt @@ -1,74 +1,31 @@ package io.invertase.googlemobileads -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import android.app.Activity +import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReadableMap -import com.google.android.gms.ads.AdLoadCallback -import com.google.android.gms.ads.LoadAdError -import com.google.android.gms.ads.admanager.AdManagerAdRequest -import com.google.android.gms.ads.rewarded.RewardedAd -import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback - -class ReactNativeGoogleMobileAdsRewardedModule(reactContext: ReactApplicationContext?) : - ReactNativeGoogleMobileAdsFullScreenAdModule(reactContext, NAME) { - override fun getAdEventName(): String { - return ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_REWARDED - } +class ReactNativeGoogleMobileAdsRewardedModule(reactContext: ReactApplicationContext?) : NativeRewardedModuleSpec(reactContext) { - @ReactMethod - fun rewardedLoad(requestId: Int, adUnitId: String, adRequestOptions: ReadableMap) { - load(requestId, adUnitId, adRequestOptions) - } - - @ReactMethod - fun rewardedShow( - requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise + private val instance: ReactNativeGoogleMobileAdsRewardedModuleImpl = ReactNativeGoogleMobileAdsRewardedModuleImpl(reactContext) + override fun rewardedLoad( + requestId: Double, + adUnitId: String, + requestOptions: ReadableMap ) { - show(requestId, adUnitId, showOptions, promise) + instance.rewardedLoad(requestId.toInt(), adUnitId,requestOptions) } - override fun loadAd( - activity: Activity, + override fun rewardedShow( + requestId: Double, adUnitId: String, - adRequest: AdManagerAdRequest, - adLoadCallback: AdLoadCallback + showOptions: ReadableMap?, + promise: Promise ) { - RewardedAd.load( - activity, - adUnitId, - adRequest, - object : - RewardedAdLoadCallback() { - override fun onAdLoaded(ad: RewardedAd) { - adLoadCallback.onAdLoaded(ad) - } - override fun onAdFailedToLoad(error: LoadAdError) { - adLoadCallback.onAdFailedToLoad(error) - } - }) + val processedShowOptions = showOptions ?: Arguments.createMap() + instance.rewardedShow(requestId.toInt(),adUnitId, processedShowOptions , promise) } - companion object { - const val NAME = "RNGoogleMobileAdsRewardedModule" + const val NAME = NativeRewardedModuleSpec.NAME } } diff --git a/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedModuleImpl.kt b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedModuleImpl.kt new file mode 100644 index 00000000..5e74ddeb --- /dev/null +++ b/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedModuleImpl.kt @@ -0,0 +1,69 @@ +package io.invertase.googlemobileads + +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import android.app.Activity +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.ReadableMap +import com.google.android.gms.ads.AdLoadCallback +import com.google.android.gms.ads.LoadAdError +import com.google.android.gms.ads.admanager.AdManagerAdRequest +import com.google.android.gms.ads.rewarded.RewardedAd +import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback + +class ReactNativeGoogleMobileAdsRewardedModuleImpl(reactContext: ReactApplicationContext?) : + ReactNativeGoogleMobileAdsFullScreenAdModule(reactContext) { + + override fun getAdEventName(): String { + return ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_REWARDED + } + + fun rewardedLoad(requestId: Int, adUnitId: String, adRequestOptions: ReadableMap) { + load(requestId, adUnitId, adRequestOptions) + } + + fun rewardedShow( + requestId: Int, adUnitId: String, showOptions: ReadableMap, promise: Promise + ) { + show(requestId, adUnitId, showOptions, promise) + } + + override fun loadAd( + activity: Activity, + adUnitId: String, + adRequest: AdManagerAdRequest, + adLoadCallback: AdLoadCallback + ) { + RewardedAd.load( + activity, + adUnitId, + adRequest, + object : + RewardedAdLoadCallback() { + override fun onAdLoaded(ad: RewardedAd) { + adLoadCallback.onAdLoaded(ad) + } + + override fun onAdFailedToLoad(error: LoadAdError) { + adLoadCallback.onAdFailedToLoad(error) + } + }) + } +} diff --git a/android/src/main/java/io/invertase/googlemobileads/common/ReactNativeModule.java b/android/src/main/java/io/invertase/googlemobileads/common/ReactNativeModule.java index 36f9356c..d6249f29 100644 --- a/android/src/main/java/io/invertase/googlemobileads/common/ReactNativeModule.java +++ b/android/src/main/java/io/invertase/googlemobileads/common/ReactNativeModule.java @@ -19,22 +19,22 @@ import android.app.Activity; import android.content.Context; + import com.facebook.react.bridge.*; + import io.invertase.googlemobileads.interfaces.ContextProvider; + import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; -import javax.annotation.Nonnull; -public class ReactNativeModule extends ReactContextBaseJavaModule implements ContextProvider { - private final TaskExecutorService executorService; +import javax.annotation.Nonnull; - private String moduleName; +public class ReactNativeModule implements ContextProvider { + private ReactApplicationContext context; - public ReactNativeModule(ReactApplicationContext reactContext, String moduleName) { - super(reactContext); - this.moduleName = moduleName; - this.executorService = new TaskExecutorService(getName()); + public ReactNativeModule(ReactApplicationContext reactContext) { + this.context = reactContext; } public static void rejectPromiseWithCodeAndMessage(Promise promise, String code, String message) { @@ -44,53 +44,16 @@ public static void rejectPromiseWithCodeAndMessage(Promise promise, String code, promise.reject(code, message, userInfoMap); } - @Override - public void initialize() { - super.initialize(); - } - public ReactContext getContext() { - return getReactApplicationContext(); - } - - public ExecutorService getExecutor() { - return executorService.getExecutor(); - } - - public ExecutorService getTransactionalExecutor() { - return executorService.getTransactionalExecutor(); - } - - public ExecutorService getTransactionalExecutor(String identifier) { - return executorService.getTransactionalExecutor(identifier); - } - - @Override - public void invalidate() { - executorService.shutdown(); + return context; } - public void removeEventListeningExecutor(String identifier) { - String executorName = executorService.getExecutorName(true, identifier); - executorService.removeExecutor(executorName); - } public Context getApplicationContext() { - return getReactApplicationContext().getApplicationContext(); + return context.getApplicationContext(); } public Activity getActivity() { - return getCurrentActivity(); - } - - @Nonnull - @Override - public String getName() { - return moduleName; - } - - @Override - public Map getConstants() { - return new HashMap<>(); + return context.getCurrentActivity(); } }