cordova-plugin-admob-nextgen 1.0.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.
@@ -0,0 +1,447 @@
1
+ package com.emi.cordova.admob.nextgen;
2
+
3
+ import android.content.Context;
4
+ import android.os.Bundle;
5
+ import android.util.DisplayMetrics;
6
+ import android.util.Log;
7
+ import android.view.View;
8
+ import android.view.ViewGroup;
9
+ import android.widget.RelativeLayout;
10
+
11
+ import androidx.annotation.NonNull;
12
+
13
+ import org.apache.cordova.CallbackContext;
14
+ import org.apache.cordova.CordovaInterface;
15
+ import org.apache.cordova.CordovaWebView;
16
+ import org.json.JSONArray;
17
+ import org.json.JSONException;
18
+ import org.json.JSONObject;
19
+
20
+ import com.google.android.libraries.ads.mobile.sdk.banner.AdSize;
21
+ import com.google.android.libraries.ads.mobile.sdk.banner.AdView;
22
+ import com.google.android.libraries.ads.mobile.sdk.banner.BannerAd;
23
+ import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdEventCallback;
24
+ import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdRefreshCallback;
25
+ import com.google.android.libraries.ads.mobile.sdk.banner.BannerAdRequest;
26
+ import com.google.android.libraries.ads.mobile.sdk.common.AdLoadCallback;
27
+ import com.google.android.libraries.ads.mobile.sdk.common.AdValue;
28
+ import com.google.android.libraries.ads.mobile.sdk.common.FullScreenContentError;
29
+ import com.google.android.libraries.ads.mobile.sdk.common.LoadAdError;
30
+
31
+ import java.util.Date;
32
+
33
+ public class BannerExecutor {
34
+
35
+ private static final String TAG = "AdMobBanner";
36
+ private CordovaInterface cordova;
37
+ private CordovaWebView webView;
38
+
39
+ private AdView adView;
40
+ private RelativeLayout adLayout;
41
+
42
+ private String lastAdUnitId = "";
43
+ private String lastSizeStr = "";
44
+ private AdSize lastAdSize = null;
45
+ private String currentPosition = "bottom";
46
+ private String lastPosition = "bottom";
47
+
48
+ private boolean isBannerVisible = false;
49
+ private boolean isLoading = false;
50
+ private boolean isOverlapping = true;
51
+ private boolean isAutoShow = true;
52
+ private boolean isCollapsible = false;
53
+
54
+ private int lastAdHeight = 0;
55
+
56
+ private long lastLoadTime = 0;
57
+ private long minLoadInterval = 5000;
58
+
59
+ public BannerExecutor(CordovaInterface cordova, CordovaWebView webView) {
60
+ this.cordova = cordova;
61
+ this.webView = webView;
62
+ }
63
+
64
+ public void createBanner(JSONArray args, CallbackContext callbackContext) {
65
+ try {
66
+ JSONObject options = args.getJSONObject(0);
67
+ String adUnitId = options.getString("adUnitId");
68
+
69
+ String requestedSize = "ADAPTIVE";
70
+ if (options.has("size")) requestedSize = options.getString("size");
71
+
72
+ String newPosition = currentPosition;
73
+ if (options.has("position")) newPosition = options.getString("position");
74
+
75
+ if (options.has("isOverlapping")) isOverlapping = options.getBoolean("isOverlapping");
76
+ if (options.has("isAutoShow")) isAutoShow = options.getBoolean("isAutoShow");
77
+ else isAutoShow = true;
78
+
79
+ if (options.has("collapsible")) this.isCollapsible = options.getBoolean("collapsible");
80
+ else this.isCollapsible = false;
81
+
82
+ if (options.has("retryInterval")) this.minLoadInterval = options.getLong("retryInterval");
83
+
84
+ final String finalSizeStr = requestedSize;
85
+ final String finalNewPosition = newPosition;
86
+
87
+ cordova.getActivity().runOnUiThread(() -> {
88
+ long currentTime = new Date().getTime();
89
+
90
+ if (isLoading) {
91
+
92
+ callbackContext.error("Banner loading");
93
+ return;
94
+ }
95
+
96
+ boolean isSameId = lastAdUnitId.equals(adUnitId);
97
+ boolean isSameSize = lastSizeStr.equals(finalSizeStr);
98
+ boolean isSamePos = lastPosition.equals(finalNewPosition);
99
+
100
+ if (adView != null && isSameId && isSameSize) {
101
+
102
+ currentPosition = finalNewPosition;
103
+
104
+ if (isAutoShow) {
105
+ if (!isBannerVisible) {
106
+ showBannerView();
107
+ callbackContext.success("Banner Shown (Cached)");
108
+ } else {
109
+ if (!isSamePos) {
110
+ updateBannerLayout();
111
+ callbackContext.success("Banner Repositioned");
112
+ } else {
113
+ callbackContext.success("Banner Already Visible");
114
+ }
115
+ }
116
+ } else {
117
+ hideBannerView();
118
+ callbackContext.success("Banner Hidden (Cached)");
119
+ }
120
+
121
+ lastPosition = currentPosition;
122
+ if (lastAdSize != null) {
123
+ sendLoadedEvent(lastAdSize, false);
124
+ }
125
+ return;
126
+ }
127
+
128
+ if ((currentTime - lastLoadTime) < minLoadInterval) {
129
+
130
+ callbackContext.error("Request too fast. Wait " + minLoadInterval + "ms");
131
+ return;
132
+ }
133
+
134
+ currentPosition = finalNewPosition;
135
+ lastPosition = currentPosition;
136
+
137
+ loadBanner(adUnitId, finalSizeStr, callbackContext);
138
+ });
139
+
140
+ } catch (JSONException e) {
141
+ callbackContext.error("Invalid JSON Args: " + e.getMessage());
142
+ }
143
+ }
144
+
145
+ private void loadBanner(String adUnitId, String sizeStr, CallbackContext callbackContext) {
146
+ Context context = cordova.getActivity();
147
+
148
+ destroyBannerInternal();
149
+
150
+ isLoading = true;
151
+ lastLoadTime = new Date().getTime();
152
+ lastAdUnitId = adUnitId;
153
+ lastSizeStr = sizeStr;
154
+
155
+ adView = new AdView(context);
156
+
157
+ AdSize adSize = getAdSize(context, sizeStr);
158
+ lastAdSize = adSize;
159
+
160
+ lastAdHeight = adSize.getHeightInPixels(context);
161
+
162
+ BannerAdRequest.Builder builder = new BannerAdRequest.Builder(adUnitId, adSize);
163
+
164
+ if (isCollapsible) {
165
+ Bundle extras = new Bundle();
166
+ String anchor = "top".equalsIgnoreCase(currentPosition) ? "top" : "bottom";
167
+ extras.putString("collapsible", anchor);
168
+ builder.setGoogleExtrasBundle(extras);
169
+ }
170
+
171
+ BannerAdRequest request = builder.build();
172
+
173
+ adView.loadAd(request, new AdLoadCallback<BannerAd>() {
174
+ @Override
175
+ public void onAdLoaded(@NonNull BannerAd bannerAd) {
176
+ cordova.getActivity().runOnUiThread(() -> {
177
+ isLoading = false;
178
+
179
+ boolean isActualCollapsible = bannerAd.isCollapsible();
180
+
181
+ bannerAd.setAdEventCallback(new BannerAdEventCallback() {
182
+ @Override
183
+ public void onAdImpression() {
184
+ fireEvent("on.banner.impression", null);
185
+ }
186
+ @Override
187
+ public void onAdClicked() {
188
+ fireEvent("on.banner.clicked", null);
189
+ }
190
+ @Override
191
+ public void onAdPaid(@NonNull AdValue adValue) {
192
+ try {
193
+ JSONObject data = new JSONObject();
194
+ data.put("value", adValue.getValueMicros());
195
+ data.put("currency", adValue.getCurrencyCode());
196
+ data.put("precision", adValue.getPrecisionType());
197
+ fireEvent("on.banner.revenue", data);
198
+ } catch (JSONException e) {}
199
+ }
200
+
201
+ @Override
202
+ public void onAdShowedFullScreenContent() {
203
+
204
+ fireEvent("on.banner.opened", null);
205
+ }
206
+
207
+ @Override
208
+ public void onAdDismissedFullScreenContent() {
209
+
210
+ fireEvent("on.banner.closed", null);
211
+ }
212
+
213
+ @Override
214
+ public void onAdFailedToShowFullScreenContent(@NonNull FullScreenContentError error) {
215
+
216
+ try {
217
+ JSONObject errData = new JSONObject();
218
+ errData.put("message", error.getMessage());
219
+ fireEvent("on.banner.failed.show", errData);
220
+ } catch (JSONException e) {}
221
+ }
222
+ });
223
+
224
+ bannerAd.setBannerAdRefreshCallback(new BannerAdRefreshCallback() {
225
+ @Override
226
+ public void onAdRefreshed() {
227
+
228
+ fireEvent("on.banner.refreshed", null);
229
+ }
230
+
231
+ @Override
232
+ public void onAdFailedToRefresh(@NonNull LoadAdError loadAdError) {
233
+
234
+ try {
235
+ JSONObject err = new JSONObject();
236
+ err.put("code", loadAdError.getCode());
237
+ err.put("message", loadAdError.getMessage());
238
+ fireEvent("on.banner.refresh.failed", err);
239
+ } catch (JSONException e) {}
240
+ }
241
+ });
242
+
243
+ sendLoadedEvent(adSize, isActualCollapsible);
244
+
245
+ if (isAutoShow) {
246
+ showBannerView();
247
+ callbackContext.success("Banner Created & Shown");
248
+ } else {
249
+ callbackContext.success("Banner Loaded (Hidden)");
250
+ }
251
+ });
252
+ }
253
+
254
+ @Override
255
+ public void onAdFailedToLoad(@NonNull LoadAdError adError) {
256
+ cordova.getActivity().runOnUiThread(() -> {
257
+ isLoading = false;
258
+
259
+ try {
260
+ JSONObject errData = new JSONObject();
261
+ errData.put("code", adError.getCode());
262
+ errData.put("message", adError.getMessage());
263
+ fireEvent("on.banner.failed", errData);
264
+ } catch (JSONException e) {}
265
+
266
+ callbackContext.error("Failed: " + adError.getMessage());
267
+ });
268
+ }
269
+ });
270
+ }
271
+
272
+ private void sendLoadedEvent(AdSize adSize, boolean isCollapsible) {
273
+ try {
274
+ Context context = cordova.getActivity();
275
+ JSONObject data = new JSONObject();
276
+ data.put("width", adSize.getWidth());
277
+ data.put("height", adSize.getHeight());
278
+ data.put("widthPixels", adSize.getWidthInPixels(context));
279
+ data.put("heightPixels", adSize.getHeightInPixels(context));
280
+ data.put("isCollapsible", isCollapsible);
281
+ fireEvent("on.banner.load", data);
282
+ } catch (JSONException e) {}
283
+ }
284
+
285
+ private AdSize getAdSize(Context context, String sizeStr) {
286
+ if ("BANNER".equalsIgnoreCase(sizeStr)) return AdSize.BANNER;
287
+ else if ("LARGE_BANNER".equalsIgnoreCase(sizeStr)) return AdSize.LARGE_BANNER;
288
+ else if ("MEDIUM_RECTANGLE".equalsIgnoreCase(sizeStr)) return AdSize.MEDIUM_RECTANGLE;
289
+ else if ("FULL_BANNER".equalsIgnoreCase(sizeStr)) return AdSize.FULL_BANNER;
290
+ else if ("LEADERBOARD".equalsIgnoreCase(sizeStr)) return AdSize.LEADERBOARD;
291
+ else return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, getAdWidth());
292
+ }
293
+
294
+ private int getAdWidth() {
295
+ DisplayMetrics displayMetrics = cordova.getActivity().getResources().getDisplayMetrics();
296
+ return (int) (displayMetrics.widthPixels / displayMetrics.density);
297
+ }
298
+
299
+ private void showBannerView() {
300
+ if (adView == null) return;
301
+
302
+ if (adLayout == null) {
303
+ adLayout = new RelativeLayout(cordova.getActivity());
304
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
305
+ RelativeLayout.LayoutParams.MATCH_PARENT,
306
+ RelativeLayout.LayoutParams.MATCH_PARENT);
307
+ adLayout.setClickable(false);
308
+ adLayout.setFocusable(false);
309
+ cordova.getActivity().addContentView(adLayout, params);
310
+ }
311
+
312
+ updateBannerLayout();
313
+
314
+ adLayout.bringToFront();
315
+ adLayout.setVisibility(View.VISIBLE);
316
+ updateWebViewMargins();
317
+ isBannerVisible = true;
318
+ }
319
+
320
+ private void updateBannerLayout() {
321
+ if (adView == null || adLayout == null) return;
322
+
323
+ if (adView.getParent() != null && adView.getParent() != adLayout) {
324
+ ((ViewGroup) adView.getParent()).removeView(adView);
325
+ }
326
+
327
+ RelativeLayout.LayoutParams bannerParams = new RelativeLayout.LayoutParams(
328
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
329
+ RelativeLayout.LayoutParams.WRAP_CONTENT);
330
+
331
+ bannerParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
332
+ if ("top".equalsIgnoreCase(currentPosition)) {
333
+ bannerParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
334
+ } else {
335
+ bannerParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
336
+ }
337
+
338
+ if (adView.getParent() == null) {
339
+ adLayout.addView(adView, bannerParams);
340
+ } else {
341
+ adView.setLayoutParams(bannerParams);
342
+ }
343
+ }
344
+
345
+ private void hideBannerView() {
346
+ if (adLayout != null) adLayout.setVisibility(View.GONE);
347
+ resetWebViewMargins();
348
+ isBannerVisible = false;
349
+ }
350
+
351
+ private void updateWebViewMargins() {
352
+ if (webView == null || webView.getView() == null) return;
353
+
354
+ View webViewView = webView.getView();
355
+ ViewGroup.LayoutParams lp = webViewView.getLayoutParams();
356
+
357
+ if (lp instanceof ViewGroup.MarginLayoutParams) {
358
+ ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) lp;
359
+
360
+ if (isOverlapping) {
361
+ params.setMargins(0, 0, 0, 0);
362
+ } else {
363
+ if ("top".equalsIgnoreCase(currentPosition)) {
364
+ params.setMargins(0, lastAdHeight, 0, 0);
365
+ } else {
366
+ params.setMargins(0, 0, 0, lastAdHeight);
367
+ }
368
+ }
369
+ webViewView.setLayoutParams(params);
370
+ webViewView.requestLayout();
371
+ }
372
+ }
373
+
374
+ private void resetWebViewMargins() {
375
+ if (webView == null || webView.getView() == null) return;
376
+ View webViewView = webView.getView();
377
+ ViewGroup.LayoutParams lp = webViewView.getLayoutParams();
378
+
379
+ if (lp instanceof ViewGroup.MarginLayoutParams) {
380
+ ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) lp;
381
+ params.setMargins(0, 0, 0, 0);
382
+ webViewView.setLayoutParams(params);
383
+ webViewView.requestLayout();
384
+ }
385
+ }
386
+
387
+ public void hideBanner(CallbackContext callbackContext) {
388
+ cordova.getActivity().runOnUiThread(() -> {
389
+ hideBannerView();
390
+ callbackContext.success();
391
+ });
392
+ }
393
+
394
+ public void showBanner(CallbackContext callbackContext) {
395
+ cordova.getActivity().runOnUiThread(() -> {
396
+ if (adView != null) {
397
+ showBannerView();
398
+ callbackContext.success();
399
+ } else {
400
+ callbackContext.error("No banner loaded");
401
+ }
402
+ });
403
+ }
404
+
405
+ private void destroyBannerInternal() {
406
+ if (adView != null) {
407
+ resetWebViewMargins();
408
+ if (adView.getParent() != null) {
409
+ ((ViewGroup) adView.getParent()).removeView(adView);
410
+ }
411
+ adView.destroy();
412
+ adView = null;
413
+ }
414
+ }
415
+
416
+ public void destroy() {
417
+ cordova.getActivity().runOnUiThread(() -> {
418
+ if (adLayout != null) {
419
+ adLayout.removeAllViews();
420
+ ((ViewGroup)adLayout.getParent()).removeView(adLayout);
421
+ adLayout = null;
422
+ }
423
+ destroyBannerInternal();
424
+ lastAdUnitId = "";
425
+ lastSizeStr = "";
426
+ lastAdSize = null;
427
+ isBannerVisible = false;
428
+ });
429
+ }
430
+
431
+ private void fireEvent(String eventName, JSONObject data) {
432
+ cordova.getActivity().runOnUiThread(() -> {
433
+ StringBuilder js = new StringBuilder();
434
+ js.append("javascript:cordova.fireDocumentEvent('");
435
+ js.append(eventName);
436
+ js.append("'");
437
+
438
+ if (data != null) {
439
+ js.append(", ");
440
+ js.append(data.toString());
441
+ }
442
+
443
+ js.append(");");
444
+ if (webView != null) webView.loadUrl(js.toString());
445
+ });
446
+ }
447
+ }