@ququplay/admob 8.0.4 → 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.
@@ -26,8 +26,6 @@ import com.google.android.gms.ads.AdSize;
26
26
  import com.google.android.gms.ads.AdView;
27
27
  import com.google.android.gms.ads.LoadAdError;
28
28
  import com.google.android.gms.common.util.BiConsumer;
29
- import androidx.core.view.ViewCompat;
30
- import androidx.core.view.WindowInsetsCompat;
31
29
 
32
30
  public class BannerExecutor extends Executor {
33
31
 
@@ -105,22 +103,23 @@ public class BannerExecutor extends Executor {
105
103
  break;
106
104
  }
107
105
 
108
- // Apply window insets for edge-to-edge support
109
- // Insets will be 0 if not in edge-to-edge mode, so this handles both cases
110
- View decorView = activitySupplier.get().getWindow().getDecorView();
111
- ViewCompat.setOnApplyWindowInsetsListener(decorView, (v, insets) -> {
112
- int bottomInset = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
113
- int topInset = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
114
-
115
- if ("TOP_CENTER".equals(adOptions.position)) {
116
- mAdViewLayoutParams.setMargins(0, topInset, 0, 0);
117
- } else {
118
- mAdViewLayoutParams.setMargins(0, 0, 0, bottomInset);
119
- }
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
+ }
120
118
 
121
- mAdViewLayout.setLayoutParams(mAdViewLayoutParams);
122
- return insets;
123
- });
119
+ mAdViewLayout.setLayoutParams(mAdViewLayoutParams);
120
+ return insets;
121
+ });
122
+ }
124
123
 
125
124
  mAdViewLayout.setLayoutParams(mAdViewLayoutParams);
126
125
 
@@ -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.4",
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
+ }