Skip to content

Commit

Permalink
Add reward interstitial support (#330)
Browse files Browse the repository at this point in the history
  • Loading branch information
lightning1377 authored Nov 27, 2024
1 parent 93d19e5 commit fbb5b9b
Show file tree
Hide file tree
Showing 22 changed files with 833 additions and 73 deletions.
323 changes: 259 additions & 64 deletions README.md

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions android/src/main/java/com/getcapacitor/community/admob/AdMob.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.getcapacitor.community.admob.interstitial.AdInterstitialExecutor;
import com.getcapacitor.community.admob.interstitial.InterstitialAdCallbackAndListeners;
import com.getcapacitor.community.admob.rewarded.AdRewardExecutor;
import com.getcapacitor.community.admob.rewardedinterstitial.AdRewardInterstitialExecutor;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.RequestConfiguration;
import com.google.android.gms.ads.initialization.InitializationStatus;
Expand All @@ -39,6 +40,12 @@ public class AdMob extends Plugin {
this::notifyListeners,
getLogTag()
);
private final AdRewardInterstitialExecutor adRewardInterstitialExecutor = new AdRewardInterstitialExecutor(
this::getContext,
this::getActivity,
this::notifyListeners,
getLogTag()
);
private final AdInterstitialExecutor adInterstitialExecutor = new AdInterstitialExecutor(
this::getContext,
this::getActivity,
Expand Down Expand Up @@ -169,6 +176,16 @@ public void showRewardVideoAd(final PluginCall call) {
adRewardExecutor.showRewardVideoAd(call, this::notifyListeners);
}

@PluginMethod
public void prepareRewardInterstitialAd(final PluginCall call) {
adRewardInterstitialExecutor.prepareRewardInterstitialAd(call, this::notifyListeners);
}

@PluginMethod
public void showRewardInterstitialAd(final PluginCall call) {
adRewardInterstitialExecutor.showRewardInterstitialAd(call, this::notifyListeners);
}

/**
* @see <a href="https://developers.google.com/admob/android/test-ads#enable_test_devices">Test Devices</a>
* @see <a href="https://developers.google.com/admob/android/targeting">Target Settings</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public abstract class AdOptions {
public static final String BANNER_TESTER_ID = "ca-app-pub-3940256099942544/6300978111";
public static final String INTERSTITIAL_TESTER_ID = "ca-app-pub-3940256099942544/1033173712";
public static final String REWARD_VIDEO_TESTER_ID = "ca-app-pub-3940256099942544/5224354917";
public static final String REWARD_INTERSTITIAL_TESTER_ID = "ca-app-pub-3940256099942544/5354046379";

/**
* The position of the ad, it can be TOP_CENTER,
Expand Down Expand Up @@ -138,6 +139,15 @@ public String getTestingId() {
};
}

public AdOptions createRewardInterstitialOptions(PluginCall call) {
return new AdOptions(call) {
@Override
public String getTestingId() {
return AdOptions.REWARD_INTERSTITIAL_TESTER_ID;
}
};
}

public AdOptions createGenericOptions(PluginCall call, final String testingID) {
return new AdOptions(call) {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.getcapacitor.community.admob.rewardedinterstitial;

import android.app.Activity;
import android.content.Context;
import androidx.core.util.Supplier;
import com.getcapacitor.JSObject;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.community.admob.helpers.AdViewIdHelper;
import com.getcapacitor.community.admob.helpers.RequestHelper;
import com.getcapacitor.community.admob.models.AdMobPluginError;
import com.getcapacitor.community.admob.models.AdOptions;
import com.getcapacitor.community.admob.models.Executor;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd;
import com.google.android.gms.common.util.BiConsumer;

public class AdRewardInterstitialExecutor extends Executor {

public static RewardedInterstitialAd mRewardedInterstitialAd;

public AdRewardInterstitialExecutor(
Supplier<Context> contextSupplier,
Supplier<Activity> activitySupplier,
BiConsumer<String, JSObject> notifyListenersFunction,
String pluginLogTag
) {
super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "AdRewardExecutor");
}

@PluginMethod
public void prepareRewardInterstitialAd(final PluginCall call, BiConsumer<String, JSObject> notifyListenersFunction) {
final AdOptions adOptions = AdOptions.getFactory().createRewardInterstitialOptions(call);

activitySupplier
.get()
.runOnUiThread(
() -> {
try {
final AdRequest adRequest = RequestHelper.createRequest(adOptions);
final String id = AdViewIdHelper.getFinalAdId(adOptions, adRequest, logTag, contextSupplier.get());
RewardedInterstitialAd.load(
contextSupplier.get(),
id,
adRequest,
RewardedInterstitialAdCallbackAndListeners.INSTANCE.getRewardedAdLoadCallback(
call,
notifyListenersFunction,
adOptions
)
);
} catch (Exception ex) {
call.reject(ex.getLocalizedMessage(), ex);
}
}
);
}

@PluginMethod
public void showRewardInterstitialAd(final PluginCall call, BiConsumer<String, JSObject> notifyListenersFunction) {
if (mRewardedInterstitialAd == null) {
String errorMessage = "No Reward Video Ad can be show. It was not prepared or maybe it failed to be prepared.";
call.reject(errorMessage);
AdMobPluginError errorObject = new AdMobPluginError(-1, errorMessage);
notifyListenersFunction.accept(RewardInterstitialAdPluginEvents.FailedToLoad, errorObject);
return;
}

try {
activitySupplier
.get()
.runOnUiThread(
() -> {
mRewardedInterstitialAd.show(
activitySupplier.get(),
RewardedInterstitialAdCallbackAndListeners.INSTANCE.getOnUserEarnedRewardListener(call, notifyListenersFunction)
);
}
);
} catch (Exception ex) {
call.reject(ex.getLocalizedMessage(), ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.getcapacitor.community.admob.rewardedinterstitial

import com.getcapacitor.community.admob.models.LoadPluginEventNames

object RewardInterstitialAdPluginEvents: LoadPluginEventNames {
const val Loaded = "onRewardedInterstitialAdLoaded"
const val FailedToLoad = "onRewardedInterstitialAdFailedToLoad"
const val Rewarded = "onRewardedInterstitialAdReward"
override val Showed = "onRewardedInterstitialAdShowed"
override val FailedToShow = "onRewardedInterstitialAdFailedToShow"
override val Dismissed = "onRewardedInterstitialAdDismissed"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.getcapacitor.community.admob.rewardedinterstitial

import com.getcapacitor.JSObject
import com.getcapacitor.PluginCall
import com.getcapacitor.community.admob.helpers.FullscreenPluginCallback
import com.getcapacitor.community.admob.models.AdMobPluginError
import com.getcapacitor.community.admob.models.AdOptions
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.OnUserEarnedRewardListener
import com.google.android.gms.ads.rewarded.RewardItem
import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd
import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAdLoadCallback
import com.google.android.gms.common.util.BiConsumer

object RewardedInterstitialAdCallbackAndListeners {

fun getOnUserEarnedRewardListener(call: PluginCall, notifyListenersFunction: BiConsumer<String, JSObject>): OnUserEarnedRewardListener {
return OnUserEarnedRewardListener { item: RewardItem ->
val response = JSObject()
response.put("type", item.type)
.put("amount", item.amount)
notifyListenersFunction.accept(RewardInterstitialAdPluginEvents.Rewarded, response)
call.resolve(response)
}
}

fun getRewardedAdLoadCallback(call: PluginCall, notifyListenersFunction: BiConsumer<String, JSObject>, adOptions: AdOptions): RewardedInterstitialAdLoadCallback {
return object : RewardedInterstitialAdLoadCallback() {
override fun onAdLoaded(ad: RewardedInterstitialAd) {
AdRewardInterstitialExecutor.mRewardedInterstitialAd = ad
AdRewardInterstitialExecutor.mRewardedInterstitialAd.fullScreenContentCallback = FullscreenPluginCallback(
RewardInterstitialAdPluginEvents, notifyListenersFunction)

val adInfo = JSObject()
adInfo.put("adUnitId", ad.adUnitId)
call.resolve(adInfo)

notifyListenersFunction.accept(RewardInterstitialAdPluginEvents.Loaded, adInfo)
}

override fun onAdFailedToLoad(adError: LoadAdError) {
val adMobError = AdMobPluginError(adError)

notifyListenersFunction.accept(RewardInterstitialAdPluginEvents.FailedToLoad, adMobError)
call.reject(adError.message)
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.getcapacitor.community.admob.rewardedinterstitial.models

import com.getcapacitor.PluginCall

class SsvInfo(
val customData: String? = null,
val userId: String? = null) {

constructor(pluginCall: PluginCall?) : this(
pluginCall?.getObject("ssv")?.getString("customData"),
pluginCall?.getObject("ssv")?.getString("userId")
)

constructor() : this(null, null)

val hasInfo
get(): Boolean {
return customData != null || userId != null
}
}
12 changes: 10 additions & 2 deletions demo/angular/src/app/shared/ad.options.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import {BannerAdOptions, BannerAdPosition, BannerAdSize} from '../../../../../dist/esm/banner';
import {AdOptions} from '../../../../../dist/esm/shared';
import {
BannerAdOptions,
BannerAdPosition,
BannerAdSize,
} from '../../../../../dist/esm/banner';
import { AdOptions } from '../../../../../dist/esm/shared';

export const bannerTopOptions: BannerAdOptions = {
adId: 'ca-app-pub-3940256099942544/2934735716',
Expand All @@ -19,6 +23,10 @@ export const rewardOptions: AdOptions = {
adId: 'ca-app-pub-3940256099942544/5224354917',
};

export const rewardInterstitialOptions: AdOptions = {
adId: 'ca-app-pub-3940256099942544/5354046379',
};

export const interstitialOptions: AdOptions = {
adId: 'ca-app-pub-3940256099942544/1033173712',
};
64 changes: 58 additions & 6 deletions ios/Plugin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
DB061C5526394B5800538D26 /* AdInterstitialExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB061C5326394B5800538D26 /* AdInterstitialExecutor.swift */; };
DB061C5926394B7900538D26 /* FullScreenAdEventName.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB061C5826394B7900538D26 /* FullScreenAdEventName.swift */; };
DBBC90F22697F1F400F2A663 /* AuthorizationStatusEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBBC90F12697F1F400F2A663 /* AuthorizationStatusEnum.swift */; };
DC44B8892C0D9749001D8B37 /* AdRewardInterstitialExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC44B8882C0D9749001D8B37 /* AdRewardInterstitialExecutor.swift */; };
DC44B88B2C0D9764001D8B37 /* RewardInterstitialAdPluginEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC44B88A2C0D9764001D8B37 /* RewardInterstitialAdPluginEvents.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -61,6 +63,8 @@
DB061C5326394B5800538D26 /* AdInterstitialExecutor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdInterstitialExecutor.swift; sourceTree = "<group>"; };
DB061C5826394B7900538D26 /* FullScreenAdEventName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullScreenAdEventName.swift; sourceTree = "<group>"; };
DBBC90F12697F1F400F2A663 /* AuthorizationStatusEnum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AuthorizationStatusEnum.swift; path = Plugin/Helper/AuthorizationStatusEnum.swift; sourceTree = SOURCE_ROOT; };
DC44B8882C0D9749001D8B37 /* AdRewardInterstitialExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdRewardInterstitialExecutor.swift; sourceTree = "<group>"; };
DC44B88A2C0D9764001D8B37 /* RewardInterstitialAdPluginEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RewardInterstitialAdPluginEvents.swift; sourceTree = "<group>"; };
F44715726BB7665615BDA523 /* Pods-Plugin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Plugin.debug.xcconfig"; path = "Target Support Files/Pods-Plugin/Pods-Plugin.debug.xcconfig"; sourceTree = "<group>"; };
FB011FA1245A5805FBC629D9 /* Pods_PluginTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PluginTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -121,6 +125,7 @@
50ADFF8A201F53D600D50D53 /* Plugin */ = {
isa = PBXGroup;
children = (
DC44B8872C0D971A001D8B37 /* RewardedInterstitial */,
BD7969362A4EA77900B13412 /* Consent */,
DBBC90F32697F26000F2A663 /* Helper */,
DB061C4926394B0400538D26 /* Rewarded */,
Expand Down Expand Up @@ -206,6 +211,15 @@
path = Helper;
sourceTree = "<group>";
};
DC44B8872C0D971A001D8B37 /* RewardedInterstitial */ = {
isa = PBXGroup;
children = (
DC44B8882C0D9749001D8B37 /* AdRewardInterstitialExecutor.swift */,
DC44B88A2C0D9764001D8B37 /* RewardInterstitialAdPluginEvents.swift */,
);
path = RewardedInterstitial;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
Expand All @@ -229,6 +243,7 @@
50ADFF84201F53D600D50D53 /* Frameworks */,
50ADFF85201F53D600D50D53 /* Headers */,
50ADFF86201F53D600D50D53 /* Resources */,
2629298625CE1F6680C13FD9 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand All @@ -248,6 +263,7 @@
50ADFF8E201F53D600D50D53 /* Frameworks */,
50ADFF8F201F53D600D50D53 /* Resources */,
A6BD04EB568905DCA6108727 /* [CP] Embed Pods Frameworks */,
3A1D71941C67BCF50F106667 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -317,6 +333,46 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
2629298625CE1F6680C13FD9 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Plugin/Pods-Plugin-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/Google-Mobile-Ads-SDK/GoogleMobileAdsResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUserMessagingPlatform/UserMessagingPlatformResources.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMobileAdsResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/UserMessagingPlatformResources.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Plugin/Pods-Plugin-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3A1D71941C67BCF50F106667 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-PluginTests/Pods-PluginTests-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/Google-Mobile-Ads-SDK/GoogleMobileAdsResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUserMessagingPlatform/UserMessagingPlatformResources.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMobileAdsResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/UserMessagingPlatformResources.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PluginTests/Pods-PluginTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
A6BD04EB568905DCA6108727 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand All @@ -326,17 +382,11 @@
"${PODS_ROOT}/Target Support Files/Pods-PluginTests/Pods-PluginTests-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/Capacitor/Capacitor.framework",
"${BUILT_PRODUCTS_DIR}/CapacitorCordova/Cordova.framework",
"${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework",
"${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework",
"${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Capacitor.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Cordova.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand Down Expand Up @@ -396,7 +446,9 @@
files = (
DB061C5426394B5800538D26 /* InterstitialAdPluginEvents.swift in Sources */,
BD7969382A4EA78C00B13412 /* ConsentExecutor.swift in Sources */,
DC44B8892C0D9749001D8B37 /* AdRewardInterstitialExecutor.swift in Sources */,
DB061C5526394B5800538D26 /* AdInterstitialExecutor.swift in Sources */,
DC44B88B2C0D9764001D8B37 /* RewardInterstitialAdPluginEvents.swift in Sources */,
DB061C5126394B4100538D26 /* AdRewardExecutor.swift in Sources */,
DBBC90F22697F1F400F2A663 /* AuthorizationStatusEnum.swift in Sources */,
DB061C44263949D800538D26 /* BannerAdPluginEvents.swift in Sources */,
Expand Down
2 changes: 2 additions & 0 deletions ios/Plugin/Plugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@
CAP_PLUGIN_METHOD(showInterstitial, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(prepareRewardVideoAd, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(showRewardVideoAd, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(prepareRewardInterstitialAd, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(showRewardInterstitialAd, CAPPluginReturnPromise);
)
Loading

0 comments on commit fbb5b9b

Please sign in to comment.