@ququplay/admob 8.2.1 → 8.2.2
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/android/src/main/java/com/getcapacitor/community/admob/consent/AdConsentExecutor.java
CHANGED
|
@@ -22,12 +22,8 @@ import java.util.List;
|
|
|
22
22
|
|
|
23
23
|
public class AdConsentExecutor extends Executor {
|
|
24
24
|
|
|
25
|
-
// Unity Ads in
|
|
26
|
-
private static final
|
|
27
|
-
|
|
28
|
-
// Consent last updated before this date (2026-10-27) may not mention Unity Ads, which joined the ad partners in
|
|
29
|
-
// October 2026. Newer consent is never asked for again on this account.
|
|
30
|
-
private static final long UNITY_ADS_CONSENT_SINCE_MILLIS = 1793059200000L;
|
|
25
|
+
// Unity Ads in the IAB TCF Global Vendor List ("Unity Technologies SF").
|
|
26
|
+
private static final int UNITY_ADS_VENDOR_ID = 1549;
|
|
31
27
|
|
|
32
28
|
private ConsentInformation consentInformation;
|
|
33
29
|
|
|
@@ -143,33 +139,9 @@ public class AdConsentExecutor extends Executor {
|
|
|
143
139
|
return true;
|
|
144
140
|
}
|
|
145
141
|
|
|
146
|
-
// 6. Consent that does not mention Unity Ads makes Unity Ads ask in its own dialog, inside an ad.
|
|
147
|
-
// Ask once more, with Unity Ads now among the ad partners.
|
|
148
|
-
long lastUpdated = lastUpdatedMillis(tcString, base64);
|
|
149
|
-
if (gdprApplies(prefs) && lastUpdated >= 0 && lastUpdated < UNITY_ADS_CONSENT_SINCE_MILLIS && unityAdsConsent(prefs) == null) {
|
|
150
|
-
clearAllTCFPreferences(prefs);
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
142
|
return false;
|
|
155
143
|
}
|
|
156
144
|
|
|
157
|
-
/** The TC string's "last updated" date (characters 7 to 12), or -1 when it is unreadable. */
|
|
158
|
-
private long lastUpdatedMillis(String tcString, String base64) {
|
|
159
|
-
if (tcString.length() < 13) {
|
|
160
|
-
return -1;
|
|
161
|
-
}
|
|
162
|
-
long deciseconds = 0L;
|
|
163
|
-
for (char c : tcString.substring(7, 13).toCharArray()) {
|
|
164
|
-
int value = base64.indexOf(c);
|
|
165
|
-
if (value == -1) {
|
|
166
|
-
return -1;
|
|
167
|
-
}
|
|
168
|
-
deciseconds = deciseconds * 64 + value;
|
|
169
|
-
}
|
|
170
|
-
return deciseconds * 100;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
145
|
private boolean gdprApplies(SharedPreferences prefs) {
|
|
174
146
|
try {
|
|
175
147
|
return prefs.getInt("IABTCF_gdprApplies", 0) == 1;
|
|
@@ -178,31 +150,21 @@ public class AdConsentExecutor extends Executor {
|
|
|
178
150
|
}
|
|
179
151
|
}
|
|
180
152
|
|
|
181
|
-
/**
|
|
182
|
-
|
|
183
|
-
* true or false, or null when the string does not mention Unity Ads.
|
|
184
|
-
*/
|
|
185
|
-
private Boolean unityAdsConsent(SharedPreferences prefs) {
|
|
186
|
-
String additionalConsent;
|
|
153
|
+
/** Whether the player agreed to personalized ads (purposes 1, 3 and 4) from Unity Ads in the TC string. */
|
|
154
|
+
private boolean unityAdsConsent(SharedPreferences prefs) {
|
|
187
155
|
try {
|
|
188
|
-
|
|
156
|
+
String purposeConsent = prefs.getString("IABTCF_PurposeConsents", "");
|
|
157
|
+
String vendorConsent = prefs.getString("IABTCF_VendorConsents", "");
|
|
158
|
+
return hasConsentFor(Arrays.asList(1, 3, 4), purposeConsent, hasAttribute(vendorConsent, UNITY_ADS_VENDOR_ID));
|
|
189
159
|
} catch (ClassCastException ex) {
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
String[] parts = additionalConsent == null ? new String[0] : additionalConsent.split("~");
|
|
193
|
-
if (parts.length > 1 && Arrays.asList(parts[1].split("\\.")).contains(UNITY_ADS_PROVIDER_ID)) {
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
if (parts.length > 2 && Arrays.asList(parts[2].split("\\.")).contains(UNITY_ADS_PROVIDER_ID)) {
|
|
197
160
|
return false;
|
|
198
161
|
}
|
|
199
|
-
return null;
|
|
200
162
|
}
|
|
201
163
|
|
|
202
164
|
/**
|
|
203
165
|
* Tells Unity Ads the player's answer, so it never shows its own consent dialog. The AdMob adapter passes it only
|
|
204
|
-
* when
|
|
205
|
-
* skip this.
|
|
166
|
+
* when Google's Additional Consent string mentions Unity Ads, which Google's consent form never does: it records
|
|
167
|
+
* Unity Ads as an IAB vendor. Apps without Unity Ads skip this.
|
|
206
168
|
*/
|
|
207
169
|
public void passConsentToUnityAds() {
|
|
208
170
|
Context context = contextSupplier.get();
|
|
@@ -210,7 +172,7 @@ public class AdConsentExecutor extends Executor {
|
|
|
210
172
|
if (!gdprApplies(prefs)) {
|
|
211
173
|
return;
|
|
212
174
|
}
|
|
213
|
-
boolean consent =
|
|
175
|
+
boolean consent = unityAdsConsent(prefs);
|
|
214
176
|
try {
|
|
215
177
|
Class<?> metaDataClass = Class.forName("com.unity3d.ads.metadata.MetaData");
|
|
216
178
|
Object metaData = metaDataClass.getConstructor(Context.class).newInstance(context.getApplicationContext());
|
|
@@ -6,12 +6,8 @@ import UserMessagingPlatform
|
|
|
6
6
|
class ConsentExecutor: NSObject {
|
|
7
7
|
weak var plugin: AdMobPlugin?
|
|
8
8
|
|
|
9
|
-
// Unity Ads in
|
|
10
|
-
private let
|
|
11
|
-
|
|
12
|
-
// Consent last updated before this date (2026-10-27) may not mention Unity Ads, which joined the ad partners in
|
|
13
|
-
// October 2026. Newer consent is never asked for again on this account.
|
|
14
|
-
private let unityAdsConsentSinceMillis: Int64 = 1793059200000
|
|
9
|
+
// Unity Ads in the IAB TCF Global Vendor List ("Unity Technologies SF").
|
|
10
|
+
private let unityAdsVendorId = 1549
|
|
15
11
|
|
|
16
12
|
func requestConsentInfo(_ call: CAPPluginCall, _ debugGeography: Int, _ testDeviceIdentifiers: [String], _ tagForUnderAgeOfConsent: Bool) {
|
|
17
13
|
let parameters = RequestParameters()
|
|
@@ -237,53 +233,24 @@ class ConsentExecutor: NSObject {
|
|
|
237
233
|
return true
|
|
238
234
|
}
|
|
239
235
|
|
|
240
|
-
// 6. Consent that does not mention Unity Ads makes Unity Ads ask in its own dialog, inside an ad.
|
|
241
|
-
// Ask once more, with Unity Ads now among the ad partners.
|
|
242
|
-
if let lastUpdated = lastUpdatedMillis(tcString, base64),
|
|
243
|
-
isGDPR() && lastUpdated < unityAdsConsentSinceMillis && unityAdsConsent(settings) == nil {
|
|
244
|
-
clearAllTCFPreferences(settings)
|
|
245
|
-
return true
|
|
246
|
-
}
|
|
247
|
-
|
|
248
236
|
return false
|
|
249
237
|
}
|
|
250
238
|
|
|
251
|
-
///
|
|
252
|
-
private func
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
var deciseconds: Int64 = 0
|
|
257
|
-
for char in tcString.dropFirst(7).prefix(6) {
|
|
258
|
-
guard let value = base64.firstIndex(of: char) else {
|
|
259
|
-
return nil
|
|
260
|
-
}
|
|
261
|
-
deciseconds = deciseconds * 64 + Int64(value.utf16Offset(in: base64))
|
|
262
|
-
}
|
|
263
|
-
return deciseconds * 100
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/// Unity Ads' answer in Google's Additional Consent string ("2~consented ids~dv.disclosed ids"):
|
|
267
|
-
/// true or false, or nil when the string does not mention Unity Ads.
|
|
268
|
-
private func unityAdsConsent(_ settings: UserDefaults) -> Bool? {
|
|
269
|
-
let parts = (settings.string(forKey: "IABTCF_AddtlConsent") ?? "").components(separatedBy: "~")
|
|
270
|
-
if parts.count > 1 && parts[1].components(separatedBy: ".").contains(unityAdsProviderId) {
|
|
271
|
-
return true
|
|
272
|
-
}
|
|
273
|
-
if parts.count > 2 && parts[2].components(separatedBy: ".").contains(unityAdsProviderId) {
|
|
274
|
-
return false
|
|
275
|
-
}
|
|
276
|
-
return nil
|
|
239
|
+
/// Whether the player agreed to personalized ads (purposes 1, 3 and 4) from Unity Ads in the TC string.
|
|
240
|
+
private func unityAdsConsent(_ settings: UserDefaults) -> Bool {
|
|
241
|
+
let purposeConsent = settings.string(forKey: "IABTCF_PurposeConsents") ?? ""
|
|
242
|
+
let vendorConsent = settings.string(forKey: "IABTCF_VendorConsents") ?? ""
|
|
243
|
+
return hasConsentFor([1, 3, 4], purposeConsent, hasAttribute(input: vendorConsent, index: unityAdsVendorId))
|
|
277
244
|
}
|
|
278
245
|
|
|
279
246
|
/// Tells Unity Ads the player's answer, so it never shows its own consent dialog. The AdMob adapter passes it only
|
|
280
|
-
/// when
|
|
281
|
-
/// skip this.
|
|
247
|
+
/// when Google's Additional Consent string mentions Unity Ads, which Google's consent form never does: it records
|
|
248
|
+
/// Unity Ads as an IAB vendor. Apps without Unity Ads skip this.
|
|
282
249
|
func passConsentToUnityAds() {
|
|
283
250
|
guard isGDPR(), let metaDataClass = NSClassFromString("UADSMetaData") as? NSObject.Type else {
|
|
284
251
|
return
|
|
285
252
|
}
|
|
286
|
-
let consent = unityAdsConsent(UserDefaults.standard)
|
|
253
|
+
let consent = unityAdsConsent(UserDefaults.standard)
|
|
287
254
|
let metaData = metaDataClass.init()
|
|
288
255
|
_ = metaData.perform(NSSelectorFromString("set:value:"), with: "gdpr.consent", with: NSNumber(value: consent))
|
|
289
256
|
_ = metaData.perform(NSSelectorFromString("commit"))
|