@capacitor-community/admob 8.1.0 → 8.2.0
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 +129 -324
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/getcapacitor/community/admob/AdMob.java +13 -3
- package/android/src/main/java/com/getcapacitor/community/admob/banner/BannerExecutor.java +261 -141
- package/android/src/main/java/com/getcapacitor/community/admob/helpers/FullscreenPluginCallback.kt +5 -1
- package/android/src/main/java/com/getcapacitor/community/admob/interstitial/AdInterstitialExecutor.java +27 -31
- package/android/src/main/java/com/getcapacitor/community/admob/interstitial/InterstitialAdCallbackAndListeners.kt +1 -1
- package/android/src/main/java/com/getcapacitor/community/admob/models/LoadPluginEventNames.kt +2 -1
- package/android/src/main/java/com/getcapacitor/community/admob/rewarded/AdRewardExecutor.java +29 -33
- package/android/src/main/java/com/getcapacitor/community/admob/rewarded/RewardAdPluginEvents.kt +2 -1
- package/android/src/main/java/com/getcapacitor/community/admob/rewarded/RewardedAdCallbackAndListeners.kt +1 -1
- package/android/src/main/java/com/getcapacitor/community/admob/rewardedinterstitial/AdRewardInterstitialExecutor.java +29 -37
- package/android/src/main/java/com/getcapacitor/community/admob/rewardedinterstitial/RewardedInterstitialAdCallbackAndListeners.kt +1 -1
- package/dist/docs.json +33 -3
- package/dist/esm/interstitial/interstitial-definitions.interface.d.ts +3 -0
- package/dist/esm/reward/reward-ad-plugin-events.enum.d.ts +4 -0
- package/dist/esm/reward/reward-ad-plugin-events.enum.js +4 -0
- package/dist/esm/reward/reward-ad-plugin-events.enum.js.map +1 -1
- package/dist/esm/reward/reward-definitions.interface.d.ts +8 -0
- package/dist/esm/reward-interstitial/reward-interstitial-definitions.interface.d.ts +3 -0
- package/dist/plugin.cjs.js +4 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +4 -0
- package/dist/plugin.js.map +1 -1
- package/docs/app-open.md +53 -0
- package/docs/banner.md +100 -0
- package/docs/configuration.md +30 -0
- package/docs/consent.md +80 -0
- package/docs/events.md +75 -0
- package/docs/interstitial.md +47 -0
- package/docs/migration.md +126 -0
- package/docs/rewarded.md +135 -0
- package/docs/testing.md +67 -0
- package/ios/Sources/AdMobPlugin/AdMobPlugin.swift +4 -1
- package/ios/Sources/AdMobPlugin/AppOpen/AppOpenAdManager.swift +1 -1
- package/ios/Sources/AdMobPlugin/Banner/BannerExecutor.swift +1 -1
- package/ios/Sources/AdMobPlugin/Interstitial/AdInterstitialExecutor.swift +3 -3
- package/ios/Sources/AdMobPlugin/Rewarded/AdRewardExecutor.swift +7 -3
- package/ios/Sources/AdMobPlugin/Rewarded/RewardAdPluginEvents.swift +1 -0
- package/ios/Sources/AdMobPlugin/RewardedInterstitial/AdRewardInterstitialExecutor.swift +3 -3
- package/package.json +3 -1
|
@@ -2,17 +2,22 @@ package com.getcapacitor.community.admob.banner;
|
|
|
2
2
|
|
|
3
3
|
import android.app.Activity;
|
|
4
4
|
import android.content.Context;
|
|
5
|
-
import android.os.
|
|
5
|
+
import android.os.Handler;
|
|
6
|
+
import android.os.Looper;
|
|
6
7
|
import android.util.DisplayMetrics;
|
|
7
8
|
import android.util.Log;
|
|
8
9
|
import android.view.Gravity;
|
|
9
10
|
import android.view.View;
|
|
10
11
|
import android.view.ViewGroup;
|
|
12
|
+
import android.view.ViewTreeObserver;
|
|
11
13
|
import android.view.WindowManager;
|
|
12
14
|
import android.widget.RelativeLayout;
|
|
13
15
|
import androidx.annotation.NonNull;
|
|
14
16
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
17
|
+
import androidx.core.graphics.Insets;
|
|
18
|
+
import androidx.core.util.Consumer;
|
|
15
19
|
import androidx.core.util.Supplier;
|
|
20
|
+
import androidx.core.view.WindowInsetsCompat;
|
|
16
21
|
import com.getcapacitor.JSObject;
|
|
17
22
|
import com.getcapacitor.PluginCall;
|
|
18
23
|
import com.getcapacitor.community.admob.helpers.AdViewIdHelper;
|
|
@@ -44,11 +49,120 @@ public class BannerExecutor extends Executor {
|
|
|
44
49
|
super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "BannerExecutor");
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
/**
|
|
53
|
+
* How long to wait for the banner parent to appear before giving up. Deliberately
|
|
54
|
+
* generous: the devices where the parent is late are the slow ones, and a premature
|
|
55
|
+
* timeout now fails AdMob.initialize() outright rather than only the banner.
|
|
56
|
+
*/
|
|
57
|
+
private static final long PARENT_TIMEOUT_MS = 5000;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Resolve the banner parent, waiting for the layout pass that adds it when it is not
|
|
61
|
+
* there yet, and report the outcome to `onResult` on the UI thread.
|
|
62
|
+
*
|
|
63
|
+
* android.R.id.content can still have no child when initialize() runs - for example
|
|
64
|
+
* when the app is relaunched quickly after being closed - and the old code cached that
|
|
65
|
+
* null for the lifetime of the process, so every later showBanner() threw
|
|
66
|
+
* NullPointerException on it. Waiting here lets AdMob.initialize() mean what callers
|
|
67
|
+
* already read it as: ready to show a banner.
|
|
68
|
+
*/
|
|
69
|
+
public void awaitViewGroup(final Consumer<Boolean> onResult) {
|
|
70
|
+
if (resolveViewGroup() != null) {
|
|
71
|
+
onResult.accept(true);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Activity activity = liveActivity();
|
|
76
|
+
View content = activity == null ? null : activity.findViewById(android.R.id.content);
|
|
77
|
+
if (!(content instanceof ViewGroup)) {
|
|
78
|
+
Log.w(logTag, "Banner parent unavailable: no usable android.R.id.content");
|
|
79
|
+
onResult.accept(false);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
final View contentView = content;
|
|
84
|
+
final Handler handler = new Handler(Looper.getMainLooper());
|
|
85
|
+
final boolean[] settled = { false };
|
|
86
|
+
final ViewTreeObserver.OnGlobalLayoutListener[] listener = new ViewTreeObserver.OnGlobalLayoutListener[1];
|
|
87
|
+
final Runnable[] timeout = new Runnable[1];
|
|
88
|
+
|
|
89
|
+
listener[0] = () -> {
|
|
90
|
+
if (settled[0] || resolveViewGroup() == null) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
settled[0] = true;
|
|
94
|
+
handler.removeCallbacks(timeout[0]);
|
|
95
|
+
removeGlobalLayoutListener(contentView, listener[0]);
|
|
96
|
+
onResult.accept(true);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
timeout[0] = () -> {
|
|
100
|
+
if (settled[0]) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
settled[0] = true;
|
|
104
|
+
removeGlobalLayoutListener(contentView, listener[0]);
|
|
105
|
+
Log.w(logTag, "Banner parent never appeared within " + PARENT_TIMEOUT_MS + "ms");
|
|
106
|
+
onResult.accept(false);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
contentView.getViewTreeObserver().addOnGlobalLayoutListener(listener[0]);
|
|
110
|
+
|
|
111
|
+
// A child added between the first attempt and registering the listener would not
|
|
112
|
+
// fire it, so try once more now that we are listening.
|
|
113
|
+
if (resolveViewGroup() != null) {
|
|
114
|
+
settled[0] = true;
|
|
115
|
+
removeGlobalLayoutListener(contentView, listener[0]);
|
|
116
|
+
onResult.accept(true);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
handler.postDelayed(timeout[0], PARENT_TIMEOUT_MS);
|
|
49
121
|
}
|
|
50
122
|
|
|
51
|
-
|
|
123
|
+
/**
|
|
124
|
+
* The banner's parent, or null while it is unavailable. Never caches a null: the
|
|
125
|
+
* lookup is retried on each use so a later call can succeed once layout has settled.
|
|
126
|
+
*/
|
|
127
|
+
private ViewGroup resolveViewGroup() {
|
|
128
|
+
if (mViewGroup != null) {
|
|
129
|
+
return mViewGroup;
|
|
130
|
+
}
|
|
131
|
+
Activity activity = liveActivity();
|
|
132
|
+
if (activity == null) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
View content = activity.findViewById(android.R.id.content);
|
|
136
|
+
if (!(content instanceof ViewGroup)) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
// Must be content's first child: showBanner builds CoordinatorLayout.LayoutParams,
|
|
140
|
+
// which android.R.id.content (a FrameLayout) rejects with a ClassCastException
|
|
141
|
+
// while measuring.
|
|
142
|
+
View child = ((ViewGroup) content).getChildAt(0);
|
|
143
|
+
if (child instanceof ViewGroup) {
|
|
144
|
+
mViewGroup = (ViewGroup) child;
|
|
145
|
+
}
|
|
146
|
+
return mViewGroup;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** The current activity, or null when it is gone or on its way out. */
|
|
150
|
+
private Activity liveActivity() {
|
|
151
|
+
Activity activity = activitySupplier.get();
|
|
152
|
+
if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
return activity;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private static void removeGlobalLayoutListener(View view, ViewTreeObserver.OnGlobalLayoutListener listener) {
|
|
159
|
+
ViewTreeObserver observer = view.getViewTreeObserver();
|
|
160
|
+
if (observer.isAlive()) {
|
|
161
|
+
observer.removeOnGlobalLayoutListener(listener);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public void showBanner(final PluginCall call, boolean systemBarsHandlesInsets) {
|
|
52
166
|
final AdOptions adOptions = AdOptions.getFactory().createBannerOptions(call);
|
|
53
167
|
float density = contextSupplier.get().getResources().getDisplayMetrics().density;
|
|
54
168
|
|
|
@@ -130,23 +244,27 @@ public class BannerExecutor extends Executor {
|
|
|
130
244
|
mAdViewLayoutParams.setMargins(sideMargin, densityMargin, sideMargin, densityMargin);
|
|
131
245
|
}
|
|
132
246
|
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
247
|
+
// Use the insets remaining after Capacitor's parent layout has handled them.
|
|
248
|
+
// Replacing the decor-view listener would override SystemBars' safe-area handling.
|
|
249
|
+
mAdViewLayout.setOnApplyWindowInsetsListener((v, insets) -> {
|
|
250
|
+
WindowInsetsCompat compat = WindowInsetsCompat.toWindowInsetsCompat(insets, v);
|
|
251
|
+
Insets safeArea = compat.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
|
252
|
+
boolean keyboardVisible =
|
|
253
|
+
compat.isVisible(WindowInsetsCompat.Type.ime()) && compat.getInsets(WindowInsetsCompat.Type.ime()).bottom > 0;
|
|
254
|
+
// SystemBars already pads the parent for the keyboard. Neither the IME
|
|
255
|
+
// height nor the navigation bar belongs in the banner's margin then.
|
|
256
|
+
// With insetsHandling=disable, the host app owns keyboard avoidance.
|
|
257
|
+
int bottomInset = keyboardVisible && systemBarsHandlesInsets ? 0 : safeArea.bottom;
|
|
258
|
+
|
|
259
|
+
if ("TOP_CENTER".equals(adOptions.position)) {
|
|
260
|
+
mAdViewLayoutParams.setMargins(margins[0], margins[1] + safeArea.top, margins[2], margins[3]);
|
|
261
|
+
} else {
|
|
262
|
+
mAdViewLayoutParams.setMargins(margins[0], margins[1], margins[2], margins[3] + bottomInset);
|
|
263
|
+
}
|
|
145
264
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
265
|
+
v.setLayoutParams(mAdViewLayoutParams);
|
|
266
|
+
return insets;
|
|
267
|
+
});
|
|
150
268
|
|
|
151
269
|
createNewAdView(adOptions);
|
|
152
270
|
|
|
@@ -163,20 +281,18 @@ public class BannerExecutor extends Executor {
|
|
|
163
281
|
}
|
|
164
282
|
|
|
165
283
|
try {
|
|
166
|
-
activitySupplier
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
mAdViewLayout.setVisibility(View.GONE);
|
|
171
|
-
mAdView.pause();
|
|
284
|
+
activitySupplier.get().runOnUiThread(() -> {
|
|
285
|
+
if (mAdViewLayout != null) {
|
|
286
|
+
mAdViewLayout.setVisibility(View.GONE);
|
|
287
|
+
mAdView.pause();
|
|
172
288
|
|
|
173
|
-
|
|
289
|
+
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(0, 0);
|
|
174
290
|
|
|
175
|
-
|
|
291
|
+
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
176
292
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
293
|
+
call.resolve();
|
|
294
|
+
}
|
|
295
|
+
});
|
|
180
296
|
} catch (Exception ex) {
|
|
181
297
|
call.reject(ex.getLocalizedMessage(), ex);
|
|
182
298
|
}
|
|
@@ -184,19 +300,17 @@ public class BannerExecutor extends Executor {
|
|
|
184
300
|
|
|
185
301
|
public void resumeBanner(final PluginCall call) {
|
|
186
302
|
try {
|
|
187
|
-
activitySupplier
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
mAdViewLayout.setVisibility(View.VISIBLE);
|
|
192
|
-
mAdView.resume();
|
|
193
|
-
|
|
194
|
-
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(mAdView);
|
|
195
|
-
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
303
|
+
activitySupplier.get().runOnUiThread(() -> {
|
|
304
|
+
if (mAdViewLayout != null && mAdView != null) {
|
|
305
|
+
mAdViewLayout.setVisibility(View.VISIBLE);
|
|
306
|
+
mAdView.resume();
|
|
196
307
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
308
|
+
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(mAdView);
|
|
309
|
+
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
310
|
+
|
|
311
|
+
Log.d(logTag, "Banner AD Resumed");
|
|
312
|
+
}
|
|
313
|
+
});
|
|
200
314
|
|
|
201
315
|
call.resolve();
|
|
202
316
|
} catch (Exception ex) {
|
|
@@ -207,19 +321,20 @@ public class BannerExecutor extends Executor {
|
|
|
207
321
|
public void removeBanner(final PluginCall call) {
|
|
208
322
|
try {
|
|
209
323
|
if (mAdView != null) {
|
|
210
|
-
activitySupplier
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (
|
|
214
|
-
|
|
215
|
-
mAdViewLayout.removeView(mAdView);
|
|
216
|
-
mAdView.destroy();
|
|
217
|
-
mAdView = null;
|
|
218
|
-
Log.d(logTag, "Banner AD Removed");
|
|
219
|
-
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(0, 0);
|
|
220
|
-
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
324
|
+
activitySupplier.get().runOnUiThread(() -> {
|
|
325
|
+
if (mAdView != null) {
|
|
326
|
+
final ViewGroup bannerParent = resolveViewGroup();
|
|
327
|
+
if (bannerParent != null) {
|
|
328
|
+
bannerParent.removeView(mAdViewLayout);
|
|
221
329
|
}
|
|
222
|
-
|
|
330
|
+
mAdViewLayout.removeView(mAdView);
|
|
331
|
+
mAdView.destroy();
|
|
332
|
+
mAdView = null;
|
|
333
|
+
Log.d(logTag, "Banner AD Removed");
|
|
334
|
+
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(0, 0);
|
|
335
|
+
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
223
338
|
}
|
|
224
339
|
|
|
225
340
|
call.resolve();
|
|
@@ -233,16 +348,14 @@ public class BannerExecutor extends Executor {
|
|
|
233
348
|
// shared field that another UI-thread task can null before this one
|
|
234
349
|
// runs; using the captured reference avoids a NullPointerException.
|
|
235
350
|
final AdView adView = mAdView;
|
|
236
|
-
activitySupplier
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
adView.loadAd(adRequest);
|
|
245
|
-
});
|
|
351
|
+
activitySupplier.get().runOnUiThread(() -> {
|
|
352
|
+
if (adView != mAdView) {
|
|
353
|
+
// Banner was removed or replaced before this task ran.
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
final AdRequest adRequest = RequestHelper.createRequest(adOptions);
|
|
357
|
+
adView.loadAd(adRequest);
|
|
358
|
+
});
|
|
246
359
|
}
|
|
247
360
|
|
|
248
361
|
/**
|
|
@@ -258,96 +371,103 @@ public class BannerExecutor extends Executor {
|
|
|
258
371
|
final AdView adView = mAdView;
|
|
259
372
|
|
|
260
373
|
// Run AdMob In Main UI Thread
|
|
261
|
-
activitySupplier
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (adView != mAdView) {
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(adView);
|
|
283
|
-
|
|
284
|
-
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
285
|
-
notifyListeners(BannerAdPluginEvents.Loaded.getWebEventName(), emptyObject);
|
|
286
|
-
super.onAdLoaded();
|
|
374
|
+
activitySupplier.get().runOnUiThread(() -> {
|
|
375
|
+
if (adView != mAdView) {
|
|
376
|
+
// Banner was removed or replaced before this task ran.
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
final AdRequest adRequest = RequestHelper.createRequest(adOptions);
|
|
380
|
+
// Assign the correct id needed
|
|
381
|
+
AdViewIdHelper.assignIdToAdView(adView, adOptions, adRequest, logTag, contextSupplier.get());
|
|
382
|
+
// Add the AdView to the view hierarchy.
|
|
383
|
+
mAdViewLayout.addView(adView);
|
|
384
|
+
// Start loading the ad.
|
|
385
|
+
adView.loadAd(adRequest);
|
|
386
|
+
adView.setAdListener(
|
|
387
|
+
new AdListener() {
|
|
388
|
+
@Override
|
|
389
|
+
public void onAdLoaded() {
|
|
390
|
+
if (adView != mAdView) {
|
|
391
|
+
return;
|
|
287
392
|
}
|
|
393
|
+
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(adView);
|
|
288
394
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
// replaced. Do not touch the current banner or emit teardown
|
|
294
|
-
// events for a view the JS layer has already discarded.
|
|
295
|
-
super.onAdFailedToLoad(adError);
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
mViewGroup.removeView(mAdViewLayout);
|
|
300
|
-
mAdViewLayout.removeView(adView);
|
|
301
|
-
adView.destroy();
|
|
302
|
-
mAdView = null;
|
|
303
|
-
|
|
304
|
-
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(0, 0);
|
|
305
|
-
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
306
|
-
|
|
307
|
-
final AdMobPluginError adMobPluginError = new AdMobPluginError(adError);
|
|
308
|
-
notifyListeners(BannerAdPluginEvents.FailedToLoad.getWebEventName(), adMobPluginError);
|
|
395
|
+
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
396
|
+
notifyListeners(BannerAdPluginEvents.Loaded.getWebEventName(), emptyObject);
|
|
397
|
+
super.onAdLoaded();
|
|
398
|
+
}
|
|
309
399
|
|
|
400
|
+
@Override
|
|
401
|
+
public void onAdFailedToLoad(@NonNull LoadAdError adError) {
|
|
402
|
+
if (adView != mAdView) {
|
|
403
|
+
// Stale callback from a banner that was already removed or
|
|
404
|
+
// replaced. Do not touch the current banner or emit teardown
|
|
405
|
+
// events for a view the JS layer has already discarded.
|
|
310
406
|
super.onAdFailedToLoad(adError);
|
|
407
|
+
return;
|
|
311
408
|
}
|
|
312
409
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
super.onAdOpened();
|
|
410
|
+
final ViewGroup bannerParent = resolveViewGroup();
|
|
411
|
+
if (bannerParent != null) {
|
|
412
|
+
bannerParent.removeView(mAdViewLayout);
|
|
317
413
|
}
|
|
414
|
+
mAdViewLayout.removeView(adView);
|
|
415
|
+
adView.destroy();
|
|
416
|
+
mAdView = null;
|
|
318
417
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
notifyListeners(BannerAdPluginEvents.Closed.getWebEventName(), emptyObject);
|
|
322
|
-
super.onAdClosed();
|
|
323
|
-
}
|
|
418
|
+
final BannerAdSizeInfo sizeInfo = new BannerAdSizeInfo(0, 0);
|
|
419
|
+
notifyListeners(BannerAdPluginEvents.SizeChanged.getWebEventName(), sizeInfo);
|
|
324
420
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
421
|
+
final AdMobPluginError adMobPluginError = new AdMobPluginError(adError);
|
|
422
|
+
notifyListeners(BannerAdPluginEvents.FailedToLoad.getWebEventName(), adMobPluginError);
|
|
423
|
+
|
|
424
|
+
super.onAdFailedToLoad(adError);
|
|
330
425
|
}
|
|
331
|
-
);
|
|
332
426
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
427
|
+
@Override
|
|
428
|
+
public void onAdOpened() {
|
|
429
|
+
notifyListeners(BannerAdPluginEvents.Opened.getWebEventName(), emptyObject);
|
|
430
|
+
super.onAdOpened();
|
|
336
431
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
impressionId = adView.getResponseInfo().getResponseId();
|
|
343
|
-
if (impressionId == null) impressionId = "";
|
|
432
|
+
|
|
433
|
+
@Override
|
|
434
|
+
public void onAdClosed() {
|
|
435
|
+
notifyListeners(BannerAdPluginEvents.Closed.getWebEventName(), emptyObject);
|
|
436
|
+
super.onAdClosed();
|
|
344
437
|
}
|
|
345
|
-
AdMobRevenueData revenueData = new AdMobRevenueData(adValue, adView.getAdUnitId(), networkName, impressionId);
|
|
346
|
-
notifyListeners(BannerAdPluginEvents.AdPaid.getWebEventName(), revenueData);
|
|
347
|
-
});
|
|
348
438
|
|
|
349
|
-
|
|
350
|
-
|
|
439
|
+
@Override
|
|
440
|
+
public void onAdImpression() {
|
|
441
|
+
notifyListeners(BannerAdPluginEvents.AdImpression.getWebEventName(), emptyObject);
|
|
442
|
+
super.onAdImpression();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
adView.setOnPaidEventListener((adValue) -> {
|
|
448
|
+
if (adView != mAdView) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
String networkName = "";
|
|
452
|
+
String impressionId = "";
|
|
453
|
+
if (adView.getResponseInfo() != null) {
|
|
454
|
+
networkName = adView.getResponseInfo().getMediationAdapterClassName();
|
|
455
|
+
if (networkName == null) networkName = "";
|
|
456
|
+
impressionId = adView.getResponseInfo().getResponseId();
|
|
457
|
+
if (impressionId == null) impressionId = "";
|
|
458
|
+
}
|
|
459
|
+
AdMobRevenueData revenueData = new AdMobRevenueData(adValue, adView.getAdUnitId(), networkName, impressionId);
|
|
460
|
+
notifyListeners(BannerAdPluginEvents.AdPaid.getWebEventName(), revenueData);
|
|
351
461
|
});
|
|
462
|
+
|
|
463
|
+
// Add AdViewLayout top of the WebView
|
|
464
|
+
final ViewGroup bannerParent = resolveViewGroup();
|
|
465
|
+
if (bannerParent != null) {
|
|
466
|
+
bannerParent.addView(mAdViewLayout);
|
|
467
|
+
mAdViewLayout.requestApplyInsets();
|
|
468
|
+
} else {
|
|
469
|
+
Log.w(logTag, "Banner not attached: parent unavailable");
|
|
470
|
+
}
|
|
471
|
+
});
|
|
352
472
|
}
|
|
353
473
|
}
|
package/android/src/main/java/com/getcapacitor/community/admob/helpers/FullscreenPluginCallback.kt
CHANGED
|
@@ -13,6 +13,10 @@ class FullscreenPluginCallback(
|
|
|
13
13
|
private val onCompleted: Runnable? = null
|
|
14
14
|
): FullScreenContentCallback() {
|
|
15
15
|
|
|
16
|
+
override fun onAdClicked() {
|
|
17
|
+
loadPluginObject.adClicked?.let { notifyListenersFunction.accept(it, JSObject()) }
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
override fun onAdShowedFullScreenContent() {
|
|
17
21
|
notifyListenersFunction.accept(loadPluginObject.Showed, JSObject())
|
|
18
22
|
}
|
|
@@ -29,4 +33,4 @@ class FullscreenPluginCallback(
|
|
|
29
33
|
onCompleted?.run()
|
|
30
34
|
notifyListenersFunction.accept(loadPluginObject.Dismissed, JSObject())
|
|
31
35
|
}
|
|
32
|
-
}
|
|
36
|
+
}
|
|
@@ -40,18 +40,16 @@ public class AdInterstitialExecutor extends Executor {
|
|
|
40
40
|
final AdOptions adOptions = factory.createInterstitialOptions(call);
|
|
41
41
|
|
|
42
42
|
try {
|
|
43
|
-
activitySupplier
|
|
44
|
-
.
|
|
45
|
-
.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
);
|
|
54
|
-
});
|
|
43
|
+
activitySupplier.get().runOnUiThread(() -> {
|
|
44
|
+
final AdRequest adRequest = RequestHelper.createRequest(adOptions);
|
|
45
|
+
final String id = AdViewIdHelper.getFinalAdId(adOptions, adRequest, logTag, contextSupplier.get());
|
|
46
|
+
InterstitialAd.load(
|
|
47
|
+
activitySupplier.get(),
|
|
48
|
+
id,
|
|
49
|
+
adRequest,
|
|
50
|
+
adCallbackAndListeners.getInterstitialAdLoadCallback(call, notifyListenersFunction)
|
|
51
|
+
);
|
|
52
|
+
});
|
|
55
53
|
} catch (Exception ex) {
|
|
56
54
|
call.reject(ex.getLocalizedMessage(), ex);
|
|
57
55
|
}
|
|
@@ -71,24 +69,22 @@ public class AdInterstitialExecutor extends Executor {
|
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
final InterstitialAd adToShow = ad;
|
|
74
|
-
activitySupplier
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
});
|
|
72
|
+
activitySupplier.get().runOnUiThread(() -> {
|
|
73
|
+
try {
|
|
74
|
+
adToShow.setFullScreenContentCallback(
|
|
75
|
+
new FullscreenPluginCallback(InterstitialAdPluginPluginEvent.INSTANCE, notifyListenersFunction, () -> {
|
|
76
|
+
preparedAds.remove(adId);
|
|
77
|
+
if (adId != null && adId.equals(lastPreparedAdId)) {
|
|
78
|
+
lastPreparedAdId = null;
|
|
79
|
+
for (String remainingAdId : preparedAds.keySet()) lastPreparedAdId = remainingAdId;
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
adToShow.show(activitySupplier.get());
|
|
84
|
+
call.resolve();
|
|
85
|
+
} catch (Exception ex) {
|
|
86
|
+
call.reject(ex.getLocalizedMessage(), ex);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
93
89
|
}
|
|
94
90
|
}
|
|
@@ -43,7 +43,7 @@ object InterstitialAdCallbackAndListeners {
|
|
|
43
43
|
val adMobError = AdMobPluginError(adError)
|
|
44
44
|
|
|
45
45
|
notifyListenersFunction.accept(InterstitialAdPluginPluginEvent.FailedToLoad, adMobError)
|
|
46
|
-
call.reject(adError.message)
|
|
46
|
+
call.reject(adError.message, adError.code.toString())
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|