cordova-plugin-admob-nextgen 1.0.8 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -71,6 +71,10 @@ We prioritize the safety of your AdMob account and the stability of your app.
71
71
 
72
72
  ## Cordova/Capacitor/Framework7 AdMob Next-Gen: Installation & Usage Guide
73
73
 
74
+ ---
75
+ > Fastest test (APK Debug): **[⚡ With github action ](https://github.com/swaplab-engine/cordova-plugin-admob-nextgen/discussions/4)** (Optional)
76
+ ---
77
+
74
78
  ## 1. Cordova or Framework7
75
79
 
76
80
  ### Option A: Via CLI
@@ -86,13 +90,19 @@ Add this to your `config.xml` to restore the plugin automatically.
86
90
  <variable name="APP_ID_IOS" value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
87
91
  </plugin>
88
92
 
93
+ ---
89
94
 
90
- ## Supporting Mediation: **[⚡ admob-mediation-suite ](https://github.com/swaplab-engine/admob-mediation-suite)** (Optional)
95
+ ## (Optional)
96
+
97
+ ### Supporting Mediation: **[⚡ admob-mediation-suite ](https://github.com/swaplab-engine/admob-mediation-suite)** (Optional)
98
+ ### Supporting Native ads: **[⚡ cordova-plugin-admob-nextgen-native ](https://github.com/swaplab-engine/cordova-plugin-admob-nextgen-native)** (Optional)
99
+
100
+ ---
91
101
 
92
102
  ## For Capacitor users
93
103
  **[⚡ Capacitor Integration: Automated Setup for AdMob Next Gen ](https://github.com/swaplab-engine/cordova-plugin-admob-nextgen/discussions/3)**.
94
104
 
95
- **[⚡ AdMob Next Gen - Starter Templates 🚀 ](https://github.com/swaplab-engine/cordova-plugin-admob-nextgen-template)**.
105
+ **[⚡ AdMob Next Gen - Starter Capacitor Templates 🚀 ](https://github.com/swaplab-engine/cordova-plugin-admob-nextgen-template)**.
96
106
 
97
107
  ---
98
108
 
@@ -141,9 +151,10 @@ Add this to your `config.xml` to restore the plugin automatically.
141
151
  // 3. Initialize the SDK
142
152
  function startSdk() {
143
153
  admobNextGen.initialize({
144
- maxAdContentRating: 'G', // 'G' || 'PG' || 'T' || 'MA' || ""
145
- tagForChildDirectedTreatment: false,
146
- tagForUnderAgeOfConsent: false
154
+ maxAdContentRating: 'G', // 'G' | 'PG' | 'T' | 'MA' | ""
155
+ tagForChildDirectedTreatment: false, // true | false | null
156
+ tagForUnderAgeOfConsent: false, // true | false | null
157
+ // isNativeValidatorDisabled: false // optional param for: cordova-plugin-admob-nextgen-native
147
158
  }, function() {
148
159
  console.log(">>> AdMob SDK Initialized & Ready <<<");
149
160
  }, function(err) {
@@ -247,10 +258,12 @@ Supports **Adaptive**, **Standard**, and **Collapsible** banners.
247
258
 
248
259
  ## 4. Native Ads (Advanced Overlay) - Android Only
249
260
 
261
+ - Recommended: **[⚡ cordova-plugin-admob-nextgen-native ](https://github.com/swaplab-engine/cordova-plugin-admob-nextgen-native)** (Android | IOS)
262
+
250
263
  High-performance native templates.
251
264
 
252
265
  ### Example A: Using Templates (Recommended)
253
-
266
+ // Android Only
254
267
  admobNextGen.createNativeAd({
255
268
  adUnitId: 'ca-app-pub-xxx/xxx',
256
269
  view: 'banner_bottom', // Presets: 'banner_top', 'banner_bottom', 'modal_center'
@@ -259,7 +272,7 @@ High-performance native templates.
259
272
  });
260
273
 
261
274
  ### Example B: Custom Position (Manual Coordinates)
262
-
275
+ // Android Only
263
276
  admobNextGen.createNativeAd({
264
277
  adUnitId: 'ca-app-pub-xxx/xxx',
265
278
  view: 'custom',
@@ -271,7 +284,7 @@ High-performance native templates.
271
284
  });
272
285
 
273
286
  ### Native Methods & Events
274
-
287
+ // Android Only
275
288
  admobNextGen.removeNativeAd();
276
289
 
277
290
  document.addEventListener('on.native.loaded', () => console.log("Native Loaded"));
@@ -307,9 +320,12 @@ Use the background engine to pool ads for 0ms latency.
307
320
  // 2. Show Instantly (from pool)
308
321
  admobNextGen.showPreloadedBanner();
309
322
 
310
- // 3. Stop Engine
323
+ // 3. Stop/Remove Engine
311
324
  admobNextGen.stopBannerPreload();
312
325
 
326
+ // 4. Hide Engine
327
+ admobNextGen.hideBannerPreload()
328
+
313
329
 
314
330
  ### Banner Events
315
331
 
@@ -352,6 +368,9 @@ Supports Auto-Resume logic.
352
368
 
353
369
  admobNextGen.showAppOpenAd();
354
370
 
371
+ ### With App Open Ad Preload
372
+ > App Open Ad Preload **[⚡ Modern ](https://github.com/swaplab-engine/cordova-plugin-admob-nextgen/tree/main/simple-example/www/js/AppOpenAdPreload.js)**
373
+
355
374
  ### App Open Events
356
375
 
357
376
  document.addEventListener('on.appopen.revenue', (data) => console.log(data));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cordova-plugin-admob-nextgen",
3
- "version": "1.0.8",
3
+ "version": "1.1.9",
4
4
  "description": "Google Mobile Ads Next Gen SDK for Cordova. High performance and modular architecture. ",
5
5
  "cordova": {
6
6
  "id": "cordova-plugin-admob-nextgen",
package/plugin.xml CHANGED
@@ -1,6 +1,6 @@
1
1
  <?xml version='1.0' encoding='utf-8'?>
2
2
  <plugin id="cordova-plugin-admob-nextgen"
3
- version="1.0.8"
3
+ version="1.1.9"
4
4
  xmlns="http://apache.org/cordova/ns/plugins/1.0"
5
5
  xmlns:android="http://schemas.android.com/apk/res/android">
6
6
 
@@ -36,6 +36,7 @@
36
36
  <source-file src="src/android/AdMobNextGen.java" target-dir="app/src/main/java/com/emi/cordova/admob/nextgen" />
37
37
  <source-file src="src/android/BannerExecutor.java" target-dir="app/src/main/java/com/emi/cordova/admob/nextgen" />
38
38
  <source-file src="src/android/BannerPreloadExecutor.java" target-dir="app/src/main/java/com/emi/cordova/admob/nextgen" />
39
+ <source-file src="src/android/AppOpenAdPreloadExecutor.java" target-dir="app/src/main/java/com/emi/cordova/admob/nextgen" />
39
40
  <source-file src="src/android/NativeExecutor.java" target-dir="app/src/main/java/com/emi/cordova/admob/nextgen" />
40
41
  <source-file src="src/android/AppOpenAdExecutor.java" target-dir="app/src/main/java/com/emi/cordova/admob/nextgen" />
41
42
  <source-file src="src/android/InterstitialExecutor.java" target-dir="app/src/main/java/com/emi/cordova/admob/nextgen" />
@@ -39,6 +39,9 @@ public class AdMobNextGen extends CordovaPlugin {
39
39
  private NativeExecutor nativeExecutor;
40
40
 
41
41
  private BannerPreloadExecutor bannerPreloadExecutor;
42
+ private AppOpenAdPreloadExecutor appOpenAdPreloadExecutor;
43
+
44
+ private boolean isNativeValidatorDisabled = true;
42
45
 
43
46
  @Override
44
47
  public void pluginInitialize() {
@@ -58,6 +61,7 @@ public class AdMobNextGen extends CordovaPlugin {
58
61
  nativeExecutor = new NativeExecutor(cordova, webView);
59
62
 
60
63
  bannerPreloadExecutor = new BannerPreloadExecutor(cordova, webView);
64
+ appOpenAdPreloadExecutor = new AppOpenAdPreloadExecutor(cordova, webView);
61
65
  }
62
66
 
63
67
  @Override
@@ -125,12 +129,30 @@ public class AdMobNextGen extends CordovaPlugin {
125
129
  return true;
126
130
  }
127
131
 
132
+ if ("hideBannerPreload".equals(action)) {
133
+ bannerPreloadExecutor.hideBanner(callbackContext);
134
+ return true;
135
+ }
136
+
128
137
  if ("removeBanner".equals(action)) {
129
138
  bannerExecutor.destroy();
130
139
  callbackContext.success();
131
140
  return true;
132
141
  }
133
142
 
143
+ if ("startAppOpenPreload".equals(action)) {
144
+ appOpenAdPreloadExecutor.startPreload(args, callbackContext);
145
+ return true;
146
+ }
147
+ if ("showPreloadedAppOpenAd".equals(action)) {
148
+ appOpenAdPreloadExecutor.showPolledAd(args, callbackContext);
149
+ return true;
150
+ }
151
+ if ("isAppOpenAdAvailable".equals(action)) {
152
+ appOpenAdPreloadExecutor.checkAdAvailable(args, callbackContext);
153
+ return true;
154
+ }
155
+
134
156
  if ("loadAppOpenAd".equals(action)) {
135
157
  if (appOpenAdExecutor != null) {
136
158
  appOpenAdExecutor.loadAd(args, callbackContext);
@@ -201,41 +223,53 @@ public class AdMobNextGen extends CordovaPlugin {
201
223
  if (appOpenAdExecutor != null && appOpenAdExecutor.shouldAutoShow()) {
202
224
  appOpenAdExecutor.showAdIfAvailable(cordova.getActivity());
203
225
  }
226
+ if (appOpenAdPreloadExecutor != null && appOpenAdPreloadExecutor.shouldAutoShow()) {
227
+ if (appOpenAdPreloadExecutor.hasAvailableAd()) {
228
+ appOpenAdPreloadExecutor.showPolledAd(null, null);
229
+ }
230
+ }
204
231
  }
205
232
 
206
233
  private void initializeSDK(JSONArray args, CallbackContext callbackContext) {
207
- String appId = getAppIdFromManifest();
208
- if (appId == null) {
209
- callbackContext.error("AdMob App ID missing");
210
- return;
211
- }
212
-
213
- cordova.getThreadPool().execute(() -> {
214
- try {
215
- InitializationConfig.Builder initConfigBuilder = new InitializationConfig.Builder(appId);
234
+ String appId = getAppIdFromManifest();
235
+ if (appId == null) {
236
+ callbackContext.error("AdMob App ID missing");
237
+ return;
238
+ }
216
239
 
217
- JSONObject configJson = args.optJSONObject(0);
240
+ cordova.getThreadPool().execute(() -> {
241
+ try {
242
+ InitializationConfig.Builder initConfigBuilder = new InitializationConfig.Builder(appId);
218
243
 
219
- if (configJson != null) {
244
+ JSONObject configJson = args.optJSONObject(0);
220
245
 
221
- RequestConfiguration requestConfig = GlobalSettingsExecutor.buildRequestConfiguration(configJson);
222
- initConfigBuilder.setRequestConfiguration(requestConfig);
223
- }
246
+ if (configJson != null) {
247
+ RequestConfiguration requestConfig = GlobalSettingsExecutor.buildRequestConfiguration(configJson);
248
+ initConfigBuilder.setRequestConfiguration(requestConfig);
224
249
 
225
- InitializationConfig config = initConfigBuilder.build();
250
+ this.isNativeValidatorDisabled = configJson.optBoolean("isNativeValidatorDisabled", true);
251
+ } else {
252
+ this.isNativeValidatorDisabled = false;
253
+ }
226
254
 
227
- MobileAds.initialize(
228
- cordova.getActivity(),
229
- config,
230
- initializationStatus -> {
231
- cordova.getActivity().runOnUiThread(() -> callbackContext.success("Initialized"));
232
- }
233
- );
234
- } catch (Exception e) {
235
- cordova.getActivity().runOnUiThread(() -> callbackContext.error(e.getMessage()));
255
+ if (this.isNativeValidatorDisabled) {
256
+ initConfigBuilder.setNativeValidatorDisabled();
236
257
  }
237
- });
238
- }
258
+
259
+ InitializationConfig config = initConfigBuilder.build();
260
+
261
+ MobileAds.initialize(
262
+ cordova.getActivity(),
263
+ config,
264
+ initializationStatus -> {
265
+ cordova.getActivity().runOnUiThread(() -> callbackContext.success("Initialized"));
266
+ }
267
+ );
268
+ } catch (Exception e) {
269
+ cordova.getActivity().runOnUiThread(() -> callbackContext.error(e.getMessage()));
270
+ }
271
+ });
272
+ }
239
273
 
240
274
  private String getAppIdFromManifest() {
241
275
  try {
@@ -0,0 +1,285 @@
1
+ package com.emi.cordova.admob.nextgen;
2
+
3
+ import android.util.Log;
4
+
5
+ import androidx.annotation.NonNull;
6
+
7
+ import org.apache.cordova.CallbackContext;
8
+ import org.apache.cordova.CordovaInterface;
9
+ import org.apache.cordova.CordovaWebView;
10
+ import org.json.JSONArray;
11
+ import org.json.JSONException;
12
+ import org.json.JSONObject;
13
+
14
+ import java.util.Date;
15
+
16
+ import com.google.android.libraries.ads.mobile.sdk.appopen.AppOpenAd;
17
+ import com.google.android.libraries.ads.mobile.sdk.appopen.AppOpenAdEventCallback;
18
+ import com.google.android.libraries.ads.mobile.sdk.appopen.AppOpenAdPreloader;
19
+ import com.google.android.libraries.ads.mobile.sdk.common.AdRequest;
20
+ import com.google.android.libraries.ads.mobile.sdk.common.AdValue;
21
+ import com.google.android.libraries.ads.mobile.sdk.common.FullScreenContentError;
22
+ import com.google.android.libraries.ads.mobile.sdk.common.LoadAdError;
23
+ import com.google.android.libraries.ads.mobile.sdk.common.PreloadCallback;
24
+ import com.google.android.libraries.ads.mobile.sdk.common.PreloadConfiguration;
25
+ import com.google.android.libraries.ads.mobile.sdk.common.ResponseInfo;
26
+
27
+ public class AppOpenAdPreloadExecutor {
28
+
29
+ private static final String TAG = "AdMobAppOpenPreload";
30
+
31
+ private CordovaInterface cordova;
32
+ private CordovaWebView webView;
33
+
34
+ private String currentAdUnitId = null;
35
+
36
+ private boolean isAutoShow = false;
37
+ private long retryInterval = 5000;
38
+
39
+ private long lastLoadTime = 0;
40
+
41
+ private boolean isShowingAd = false;
42
+ private long lastAdDismissTime = 0;
43
+
44
+ public AppOpenAdPreloadExecutor(CordovaInterface cordova, CordovaWebView webView) {
45
+ this.cordova = cordova;
46
+ this.webView = webView;
47
+ }
48
+
49
+ public void startPreload(JSONArray args, CallbackContext callbackContext) {
50
+ try {
51
+ long currentTime = new Date().getTime();
52
+ String adUnitId = null;
53
+
54
+ if (args != null && args.length() > 0) {
55
+ JSONObject options = args.optJSONObject(0);
56
+ if (options != null) {
57
+ if (options.has("adUnitId")) {
58
+ adUnitId = options.getString("adUnitId");
59
+ }
60
+ if (options.has("isAutoShow")) {
61
+ this.isAutoShow = options.getBoolean("isAutoShow");
62
+ }
63
+ if (options.has("retryInterval")) {
64
+ this.retryInterval = options.getLong("retryInterval");
65
+ }
66
+ } else {
67
+ adUnitId = args.getString(0);
68
+ }
69
+ } else {
70
+
71
+ if (callbackContext != null) callbackContext.error("adUnitId is required");
72
+ return;
73
+ }
74
+
75
+ if (adUnitId != null) {
76
+ this.currentAdUnitId = adUnitId;
77
+ }
78
+
79
+ if ((currentTime - lastLoadTime) < retryInterval) {
80
+ if (callbackContext != null) {
81
+ callbackContext.success("Preload request debounced.");
82
+ }
83
+ return;
84
+ }
85
+
86
+ lastLoadTime = currentTime;
87
+
88
+ PreloadCallback preloadCallback = new PreloadCallback() {
89
+ @Override
90
+ public void onAdFailedToPreload(@NonNull String preloadId, @NonNull LoadAdError loadAdError) {
91
+ try {
92
+ JSONObject errData = new JSONObject();
93
+ errData.put("preloadId", preloadId);
94
+ errData.put("code", loadAdError.getCode());
95
+ errData.put("message", loadAdError.getMessage());
96
+ fireEvent("on.appopen.preload.failed", errData);
97
+ } catch (JSONException ignored) {}
98
+ }
99
+
100
+ @Override
101
+ public void onAdsExhausted(@NonNull String preloadId) {
102
+ try {
103
+ JSONObject data = new JSONObject();
104
+ data.put("preloadId", preloadId);
105
+ fireEvent("on.appopen.preload.exhausted", data);
106
+ } catch (JSONException ignored) {}
107
+ }
108
+
109
+ @Override
110
+ public void onAdPreloaded(@NonNull String preloadId, @NonNull ResponseInfo responseInfo) {
111
+ try {
112
+ JSONObject data = new JSONObject();
113
+ data.put("preloadId", preloadId);
114
+ fireEvent("on.appopen.preload.loaded", data);
115
+ } catch (JSONException ignored) {}
116
+ }
117
+ };
118
+
119
+ AdRequest adRequest = new AdRequest.Builder(this.currentAdUnitId).build();
120
+ PreloadConfiguration preloadConfiguration = new PreloadConfiguration(adRequest);
121
+
122
+ cordova.getActivity().runOnUiThread(() -> {
123
+ AppOpenAdPreloader.start(this.currentAdUnitId, preloadConfiguration, preloadCallback);
124
+ if (callbackContext != null) {
125
+ callbackContext.success("App open preload started");
126
+ }
127
+ });
128
+
129
+ } catch (Exception e) {
130
+ if (callbackContext != null) {
131
+ callbackContext.error("Exception: " + e.getMessage());
132
+ }
133
+ }
134
+ }
135
+
136
+ public void showPolledAd(JSONArray args, CallbackContext callbackContext) {
137
+ if (isShowingAd) {
138
+
139
+ if (callbackContext != null) callbackContext.error("Ad already showing.");
140
+ return;
141
+ }
142
+
143
+ if (new Date().getTime() - lastAdDismissTime < 1000) {
144
+
145
+ if (callbackContext != null) callbackContext.error("Ad in cooldown period.");
146
+ return;
147
+ }
148
+
149
+ try {
150
+ String adUnitId = this.currentAdUnitId;
151
+
152
+ if (args != null && args.length() > 0) {
153
+ JSONObject options = args.optJSONObject(0);
154
+ if (options != null && options.has("adUnitId")) {
155
+ adUnitId = options.getString("adUnitId");
156
+ } else {
157
+ String stringArg = args.optString(0, null);
158
+ if (stringArg != null && !stringArg.isEmpty() && !stringArg.equals("null")) {
159
+ adUnitId = stringArg;
160
+ }
161
+ }
162
+ }
163
+
164
+ if (adUnitId == null) {
165
+ if (callbackContext != null) callbackContext.error("No Ad Unit ID available.");
166
+ return;
167
+ }
168
+
169
+ final String finalAdUnitId = adUnitId;
170
+
171
+ this.isShowingAd = true;
172
+
173
+ cordova.getActivity().runOnUiThread(() -> {
174
+ AppOpenAd ad = AppOpenAdPreloader.pollAd(finalAdUnitId);
175
+
176
+ if (ad == null) {
177
+
178
+ this.isShowingAd = false;
179
+
180
+ try {
181
+ JSONObject errData = new JSONObject();
182
+ errData.put("message", "No preloaded app open ads available.");
183
+ fireEvent("on.appopen.preload.failed.show", errData);
184
+ } catch (JSONException ignored) {}
185
+
186
+ if (callbackContext != null) {
187
+ callbackContext.error("No preloaded app open ads available.");
188
+ }
189
+ return;
190
+ }
191
+
192
+ ad.setAdEventCallback(new AppOpenAdEventCallback() {
193
+ @Override
194
+ public void onAdPaid(@NonNull AdValue adValue) {
195
+ try {
196
+ JSONObject data = new JSONObject();
197
+ data.put("value", adValue.getValueMicros());
198
+ data.put("currency", adValue.getCurrencyCode());
199
+ data.put("precision", adValue.getPrecisionType());
200
+ fireEvent("on.appopen.preload.revenue", data);
201
+ } catch (JSONException ignored) {}
202
+ }
203
+
204
+ @Override
205
+ public void onAdShowedFullScreenContent() {
206
+ fireEvent("on.appopen.preload.shown", null);
207
+ }
208
+
209
+ @Override
210
+ public void onAdDismissedFullScreenContent() {
211
+ isShowingAd = false;
212
+ lastAdDismissTime = new Date().getTime();
213
+ fireEvent("on.appopen.preload.dismissed", null);
214
+ }
215
+
216
+ @Override
217
+ public void onAdFailedToShowFullScreenContent(@NonNull FullScreenContentError error) {
218
+ isShowingAd = false;
219
+ try {
220
+ JSONObject errData = new JSONObject();
221
+ errData.put("code", error.getCode());
222
+ errData.put("message", error.getMessage());
223
+ fireEvent("on.appopen.preload.failed.show", errData);
224
+ } catch (JSONException ignored) {}
225
+ }
226
+
227
+ @Override
228
+ public void onAdImpression() {
229
+ fireEvent("on.appopen.preload.impression", null);
230
+ }
231
+
232
+ @Override
233
+ public void onAdClicked() {
234
+ fireEvent("on.appopen.preload.clicked", null);
235
+ }
236
+ });
237
+
238
+ ad.show(cordova.getActivity());
239
+
240
+ if (callbackContext != null) {
241
+ callbackContext.success("Showing preloaded app open ad");
242
+ }
243
+ });
244
+
245
+ } catch (Exception e) {
246
+ this.isShowingAd = false;
247
+
248
+ if (callbackContext != null) callbackContext.error("Exception: " + e.getMessage());
249
+ }
250
+ }
251
+
252
+ public void checkAdAvailable(JSONArray args, CallbackContext callbackContext) {
253
+ boolean available = hasAvailableAd();
254
+ if (callbackContext != null) {
255
+ callbackContext.success(available ? 1 : 0);
256
+ }
257
+ }
258
+
259
+ public boolean shouldAutoShow() {
260
+ return this.isAutoShow;
261
+ }
262
+
263
+ public boolean hasAvailableAd() {
264
+ if (this.currentAdUnitId == null) return false;
265
+ return AppOpenAdPreloader.isAdAvailable(this.currentAdUnitId);
266
+ }
267
+
268
+ private void fireEvent(String eventName, JSONObject data) {
269
+ if (cordova == null) return;
270
+ cordova.getActivity().runOnUiThread(() -> {
271
+ StringBuilder js = new StringBuilder();
272
+ js.append("javascript:cordova.fireDocumentEvent('");
273
+ js.append(eventName);
274
+ js.append("'");
275
+ if (data != null) {
276
+ js.append(", ");
277
+ js.append(data.toString());
278
+ }
279
+ js.append(");");
280
+ if (webView != null && webView.getView() != null) {
281
+ webView.loadUrl(js.toString());
282
+ }
283
+ });
284
+ }
285
+ }