@ququplay/admob 8.0.5 → 8.0.6

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.
@@ -13,8 +13,6 @@ import android.widget.RelativeLayout;
13
13
  import androidx.annotation.NonNull;
14
14
  import androidx.coordinatorlayout.widget.CoordinatorLayout;
15
15
  import androidx.core.util.Supplier;
16
- import androidx.core.view.ViewCompat;
17
- import androidx.core.view.WindowInsetsCompat;
18
16
  import com.getcapacitor.JSObject;
19
17
  import com.getcapacitor.PluginCall;
20
18
  import com.getcapacitor.community.admob.helpers.AdViewIdHelper;
@@ -35,7 +33,6 @@ public class BannerExecutor extends Executor {
35
33
  private RelativeLayout mAdViewLayout;
36
34
  private AdView mAdView;
37
35
  private ViewGroup mViewGroup;
38
- private CoordinatorLayout.LayoutParams mAdViewLayoutParams;
39
36
 
40
37
  public BannerExecutor(
41
38
  Supplier<Context> contextSupplier,
@@ -88,7 +85,7 @@ public class BannerExecutor extends Executor {
88
85
  mAdViewLayout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL);
89
86
  mAdViewLayout.setVerticalGravity(Gravity.BOTTOM);
90
87
 
91
- mAdViewLayoutParams = new CoordinatorLayout.LayoutParams(
88
+ final CoordinatorLayout.LayoutParams mAdViewLayoutParams = new CoordinatorLayout.LayoutParams(
92
89
  CoordinatorLayout.LayoutParams.WRAP_CONTENT,
93
90
  CoordinatorLayout.LayoutParams.WRAP_CONTENT
94
91
  );
@@ -106,37 +103,45 @@ public class BannerExecutor extends Executor {
106
103
  break;
107
104
  }
108
105
 
106
+ // set Safe Area only for Android 15+
107
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
108
+ View rootView = activitySupplier.get().getWindow().getDecorView();
109
+ rootView.setOnApplyWindowInsetsListener((v, insets) -> {
110
+ int bottomInset = insets.getSystemWindowInsetBottom();
111
+ int topInset = insets.getSystemWindowInsetTop();
112
+
113
+ if ("TOP_CENTER".equals(adOptions.position)) {
114
+ mAdViewLayoutParams.setMargins(0, topInset, 0, 0);
115
+ } else {
116
+ mAdViewLayoutParams.setMargins(0, 0, 0, bottomInset);
117
+ }
118
+
119
+ mAdViewLayout.setLayoutParams(mAdViewLayoutParams);
120
+ return insets;
121
+ });
122
+ }
123
+
124
+ mAdViewLayout.setLayoutParams(mAdViewLayoutParams);
125
+
109
126
  int densityMargin = (int) (adOptions.margin * density);
110
127
 
111
128
  // Center Banner Ads
112
129
  int adWidth = (int) (adOptions.adSize.getSize().getWidth() * density);
113
130
 
114
- final int baseSideMargin;
115
131
  if (adWidth <= 0 || adOptions.adSize.toString().equals("ADAPTIVE_BANNER")) {
116
132
  int margin = 0;
117
133
  if (fullscreen) {
118
134
  margin = (realWidthPixels - defaultWidthPixels) / 2;
119
135
  }
120
- baseSideMargin = margin;
136
+ mAdViewLayoutParams.setMargins(margin, densityMargin, margin, densityMargin);
121
137
  } else {
122
138
  int sideMargin = ((int) defaultWidthPixels - adWidth) / 2;
123
139
  if (fullscreen) {
124
140
  sideMargin = (realWidthPixels - adWidth) / 2;
125
141
  }
126
- baseSideMargin = sideMargin;
127
- }
128
-
129
- applyBannerMargins(adOptions, baseSideMargin, densityMargin);
130
-
131
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
132
- ViewCompat.setOnApplyWindowInsetsListener(mAdViewLayout, (v, insets) -> {
133
- applyBannerMargins(adOptions, baseSideMargin, densityMargin);
134
- return insets;
135
- });
142
+ mAdViewLayoutParams.setMargins(sideMargin, densityMargin, sideMargin, densityMargin);
136
143
  }
137
144
 
138
- mAdViewLayout.setLayoutParams(mAdViewLayoutParams);
139
-
140
145
  createNewAdView(adOptions);
141
146
 
142
147
  call.resolve();
@@ -226,27 +231,6 @@ public class BannerExecutor extends Executor {
226
231
  });
227
232
  }
228
233
 
229
- private void applyBannerMargins(AdOptions adOptions, int sideMargin, int densityMargin) {
230
- int topInset = 0;
231
- int bottomInset = 0;
232
-
233
- WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(mAdViewLayout != null ? mAdViewLayout : mViewGroup);
234
- if (insets != null) {
235
- topInset = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
236
- bottomInset = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
237
- }
238
-
239
- if ("TOP_CENTER".equals(adOptions.position)) {
240
- mAdViewLayoutParams.setMargins(sideMargin, densityMargin + topInset, sideMargin, 0);
241
- } else {
242
- mAdViewLayoutParams.setMargins(sideMargin, densityMargin, sideMargin, densityMargin + bottomInset);
243
- }
244
-
245
- if (mAdViewLayout != null) {
246
- mAdViewLayout.setLayoutParams(mAdViewLayoutParams);
247
- }
248
- }
249
-
250
234
  /**
251
235
  * Follow iOS method Name:
252
236
  * https://developers.google.com/admob/ios/banner?hl=ja
@@ -61,38 +61,76 @@ public class AdConsentExecutor extends Executor {
61
61
  );
62
62
  }
63
63
 
64
+ /**
65
+ * Erases ALL core IAB TCF records simultaneously to prevent leaving
66
+ * orphaned consent data that will crash Google Ad serving.
67
+ */
68
+ private void clearAllTCFPreferences(SharedPreferences prefs) {
69
+ prefs
70
+ .edit()
71
+ .remove("IABTCF_TCString")
72
+ .remove("IABTCF_PurposeConsents")
73
+ .remove("IABTCF_VendorConsents")
74
+ .remove("IABTCF_PurposeLegitimateInterests")
75
+ .remove("IABTCF_VendorLegitimateInterests")
76
+ .remove("IABTCF_gdprApplies") // Force SDK to reassess context
77
+ .apply();
78
+ Log.w(logTag, "Successfully purged all IABTCF tracking variables from SharedPreferences.");
79
+ }
80
+
64
81
  public boolean isConsentOutdated() {
65
82
  Context context = contextSupplier.get();
66
83
  SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
84
+
67
85
  String tcString = prefs.getString("IABTCF_TCString", "");
68
86
 
69
87
  if (tcString == null || tcString.isEmpty()) {
70
88
  return false;
71
89
  }
72
90
 
73
- // base64 alphabet used to store data in IABTCF string
91
+ // 1. Safety Boundary Check: If string is way too short, it's corrupted.
92
+ if (tcString.length() < 7) {
93
+ clearAllTCFPreferences(prefs);
94
+ return true;
95
+ }
96
+
97
+ // Base64url alphabet used in IAB TCF specifications
74
98
  String base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
75
99
 
76
- // date is stored in digits 1..7 of the IABTCF string
100
+ // 2. Extract and Validate TCF Specification Version (First 6 bits / 1st character)
101
+ char versionChar = tcString.charAt(0);
102
+ int tcfVersion = base64.indexOf(versionChar);
103
+
104
+ // TCF v2.0 through v2.3 strings all use a '2' value in the version bit field
105
+ if (tcfVersion != 2) {
106
+ clearAllTCFPreferences(prefs);
107
+ return true;
108
+ }
109
+
110
+ // 3. Extract and Parse Timestamp (Characters at indexes 1 through 6 inclusive)
77
111
  String dateSubstring = tcString.substring(1, 7);
78
112
 
79
- // interpret date substring as base64-encoded integer value
80
113
  long timestamp = 0L;
81
-
82
114
  for (char c : dateSubstring.toCharArray()) {
83
115
  int value = base64.indexOf(c);
116
+ if (value == -1) {
117
+ clearAllTCFPreferences(prefs);
118
+ return true;
119
+ }
84
120
  timestamp = timestamp * 64 + value;
85
121
  }
86
122
 
87
- // timestamp is given in deci-seconds, convert to milliseconds
123
+ // Timestamp is given in deci-seconds, convert to milliseconds
88
124
  timestamp *= 100;
89
125
 
90
- // compare with current timestamp to get age in days
126
+ // 4. Calculate Age in Days
91
127
  long daysAgo = (System.currentTimeMillis() - timestamp) / (1000 * 60 * 60 * 24);
92
128
 
93
- // delete TC string if age is over a year
94
- if (daysAgo > 365) {
95
- prefs.edit().remove("IABTCF_TCString").apply();
129
+ // 5. Enforce Expiration Hard Limits
130
+ // Google hard-caps ad server acceptance at 395 days (13 months).
131
+ // The IAB TCF policy requires CMP re-checks at 365 days (12 months).
132
+ if (daysAgo > 365 || daysAgo < 0) {
133
+ clearAllTCFPreferences(prefs);
96
134
  return true;
97
135
  }
98
136
 
@@ -163,12 +201,16 @@ public class AdConsentExecutor extends Executor {
163
201
  activitySupplier.get(),
164
202
  consentRequestParameters,
165
203
  () -> {
204
+ // Check (and possibly purge) outdated consent before reading the
205
+ // remaining values, so they reflect the post-cleanup state.
206
+ boolean isConsentOutdated = isConsentOutdated();
207
+
166
208
  JSObject consentInfo = new JSObject();
167
209
  consentInfo.put("status", getConsentStatusString(consentInformation.getConsentStatus()));
168
210
  consentInfo.put("isConsentFormAvailable", consentInformation.isConsentFormAvailable());
211
+ consentInfo.put("isConsentOutdated", isConsentOutdated);
169
212
  consentInfo.put("canShowAds", canShowAds());
170
213
  consentInfo.put("canShowPersonalizedAds", canShowPersonalizedAds());
171
- consentInfo.put("isConsentOutdated", isConsentOutdated());
172
214
  consentInfo.put("canRequestAds", consentInformation.canRequestAds());
173
215
  consentInfo.put("privacyOptionsRequirementStatus", consentInformation.getPrivacyOptionsRequirementStatus().name());
174
216
  call.resolve(consentInfo);
@@ -223,6 +265,10 @@ public class AdConsentExecutor extends Executor {
223
265
  if (formError != null) {
224
266
  call.reject("Error when show consent form", formError.getMessage());
225
267
  } else {
268
+ // Check (and possibly purge) outdated consent before reading the
269
+ // remaining values, so they reflect the post-cleanup state.
270
+ boolean isConsentOutdated = isConsentOutdated();
271
+
226
272
  JSObject consentFormInfo = new JSObject();
227
273
  consentFormInfo.put("status", getConsentStatusString(consentInformation.getConsentStatus()));
228
274
  consentFormInfo.put("isConsentFormAvailable", consentInformation.isConsentFormAvailable());
@@ -231,9 +277,9 @@ public class AdConsentExecutor extends Executor {
231
277
  "privacyOptionsRequirementStatus",
232
278
  consentInformation.getPrivacyOptionsRequirementStatus().name()
233
279
  );
280
+ consentFormInfo.put("isConsentOutdated", isConsentOutdated);
234
281
  consentFormInfo.put("canShowAds", canShowAds());
235
282
  consentFormInfo.put("canShowPersonalizedAds", canShowPersonalizedAds());
236
- consentFormInfo.put("isConsentOutdated", isConsentOutdated());
237
283
 
238
284
  call.resolve(consentFormInfo);
239
285
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ququplay/admob",
3
- "version": "8.0.5",
3
+ "version": "8.0.6",
4
4
  "description": "A native plugin for AdMob",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -98,4 +98,4 @@
98
98
  "src": "android"
99
99
  }
100
100
  }
101
- }
101
+ }