Ich habe Admob für viele Jahre für viele Jahre in meinen Apps verwendet. Irgendwann musste ich den neuen Dialog der DSGVO -Einwilligung hinzufügen, damit er gemäß den neuen EU -Regeln verwendet werden konnte, und admob SDK ihre Ergebnisse automatisch verwendet. Sdk. Nur wenige Werbequellen erhalten automatisch den Wert aus dem, was der Benutzer ausgewählt hat. Tatsächlich habe ich nur sehr wenige gefunden, die es tun: Applovin und wahrscheinlich auch Minteglal (benötigt zusätzlichen Code vor der Initialisierung, aber das ist es). (COPPA):
https://developers.google.com/admob/and ... ab-support
Ding ist nicht, was ich für die verschiedenen Ad-Net-Networks nicht für sie einstellen muss. Applovin (und wahrscheinlich auch Mintesintegral) überprüft den US-Teil des SDK nicht.
Was ich in der Vergangenheit gefunden habe. />[*]https://stackoverflow.com/a/68310602/878126
Ich habe beispielsweise Folgendes erstellt:
Code: Select all
@WorkerThread
fun isGDPR(context: Context): Boolean? {
val prefs = PreferenceUtil.getDefaultSharedPreferences(context)
val gdpr =
if (prefs.contains("IABTCF_gdprApplies"))
prefs.getInt("IABTCF_gdprApplies", 0)
else return null
return gdpr == 1
}
@WorkerThread
fun canShowPersonalizedAds(context: Context): Boolean {
val prefs = PreferenceUtil.getDefaultSharedPreferences(context)
//https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details
//https://support.google.com/admob/answer/9760862?hl=en&ref_topic=9756841
val purposeConsent = prefs.getString("IABTCF_PurposeConsents", "") ?: ""
val vendorConsent = prefs.getString("IABTCF_VendorConsents", "") ?: ""
val vendorLI = prefs.getString("IABTCF_VendorLegitimateInterests", "") ?: ""
val purposeLI = prefs.getString("IABTCF_PurposeLegitimateInterests", "") ?: ""
val googleId = 755
val hasGoogleVendorConsent = hasAttribute(vendorConsent, index = googleId)
val hasGoogleVendorLI = hasAttribute(vendorLI, index = googleId)
return hasConsentFor(listOf(1, 3, 4), purposeConsent, hasGoogleVendorConsent)
&& hasConsentOrLegitimateInterestFor(listOf(2, 7, 9, 10), purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI)
}
// Check if a binary string has a "1" at position "index" (1-based)
private fun hasAttribute(input: String, index: Int): Boolean {
return input.length >= index && input[index - 1] == '1'
}
// Check if consent is given for a list of purposes
private fun hasConsentFor(purposes: List, purposeConsent: String, hasVendorConsent: Boolean): Boolean {
return purposes.all { p -> hasAttribute(purposeConsent, p) } && hasVendorConsent
}
// Check if a vendor either has consent or legitimate interest for a list of purposes
private fun hasConsentOrLegitimateInterestFor(purposes: List, purposeConsent: String, purposeLI: String, hasVendorConsent: Boolean, hasVendorLI: Boolean): Boolean {
return purposes.all { p ->
(hasVendorLI && hasAttribute(purposeLI, p)) ||
(hasVendorConsent && hasAttribute(purposeConsent, p))
}
}
< /code>
Und auch Folgendes: < /p>
/**
* Checks the stored IABTCF configuration and returns one of the values defined in [AdConfiguration],
* based on the necessary minimum consent/interest defined here: https://support.google.com/admob/answer/9760862
*/
fun detectAdConfiguration(context: Context): AdConfiguration {
// default string for "no consent", used in cases where no configuration has previously been stored
val defaultPurposeString = "0000000000"
// IABTCF strings are stored in SharedPreferences
val sharedPrefs = PreferenceUtil.getDefaultSharedPreferences(context)
// https://developers.google.com/admob/android/privacy/ad-serving-modes
//limited ads: nothing for 1, consent/legitimate: 2,7,9,10
//non personalized ads: Consent: 1 , consent/legitimate: 2,7,9,10
//personalized: consent: 1,3,4 consent/legitimate: 2,7,9,10
//
// relevant strings are those for purpose consent or legitimate interest, as well as vendors
val tcConsentString = sharedPrefs
.getString("IABTCF_PurposeConsents", defaultPurposeString) ?: defaultPurposeString
val tcInterestString = sharedPrefs
.getString("IABTCF_PurposeLegitimateInterests", defaultPurposeString)
?: defaultPurposeString
// Log.d("AppLog", "detectAdConfiguration tcConsentString:$tcConsentString tcInterestString:$tcInterestString tcVendorString:$tcVendorString ")
// in any case we need at least legitimate interest for purposes N = 2, 7, 9 and 10,
// stored in positions N-1 of either purpose string:
val sufficientInterest =
(tcConsentString.getOrNull(1) == '1' || tcInterestString.getOrNull(1) == '1') &&
(tcConsentString.getOrNull(6) == '1' || tcInterestString.getOrNull(6) == '1') &&
(tcConsentString.getOrNull(8) == '1' || tcInterestString.getOrNull(8) == '1') &&
(tcConsentString.getOrNull(9) == '1' || tcInterestString.getOrNull(9) == '1')
if (!sufficientInterest) {
return AdConfiguration.None
}
val tcVendorString = sharedPrefs.getString("IABTCF_VendorConsents", "0") ?: "0"
// Log.d("AppLog", "tcVendorString:$tcVendorString")
// TODO vendor configuration is variable, so needs to be defined by the individual developer
// - run app and make sure that a valid configuration is stored
// - have the app log the value of [tcVendorString], then copy that value to the following line
// - repeat if ad configuration changes, perhaps make this value available via remote configuration instead
val goodVendorConfiguration = context.getString(R.string.ad_consent_expected_good_vendor_configuration)
// if the stored string is shorter than what is necessary, at least some vendors will not be
// configured properly.
if (tcVendorString.length < goodVendorConfiguration.length) {
return AdConfiguration.Unclear
}
// we need consent for the following purposes N, stored in positions N-1 of the consent string:
// 1, 3 and 4 to show all ads
// 1 to show non-personalized ads
// no consent to show limited ads
val maxAdDisplayConfiguration = when {
tcConsentString.getOrNull(0) != '1' -> AdConfiguration.Limited
tcConsentString.getOrNull(2) == '1' && tcConsentString.getOrNull(3) == '1' -> AdConfiguration.All
else -> AdConfiguration.NonPersonalized
}
// build a regex that must match all '1' but not the '0' characters in goodVendorConfiguration,
// and allows this configuration to be shorter than the string it is compared with
val vendorRegex = Regex(goodVendorConfiguration.replace("0", ".").plus(".*"))
//if the regex matches, at least some ads should be served; if not, vendor string is unclear
return if (vendorRegex.matches(tcVendorString)) {
maxAdDisplayConfiguration
} else {
return AdConfiguration.Unclear
}
}
< /code>
Aber ich denke, ich kann diese nur zur Erkennung von Admob verwenden (weil "755" von Admob ist, wie hier gezeigt, aber es gibt andere, und vielleicht haben sie andere Regeln) oder einfach alle zu akzeptieren und nicht speziell für die verschiedenen Ad-Sources. Außerdem ist es nur für DSGVO und nicht auch von US-Regeln. Wenn IABTCF_GDPRAPPLIES
Code: Select all
IABGPP_GppSID
https://developers Wählen Sie "nicht verkaufen oder meine Daten teilen". Ich bekomme diese zu den Standard -SharedPreferences hinzugefügt: < /p>
7
DBABL~BVQVAAAAAg
< /code>
Wenn ich mich für das Teilen entscheide, ändert es den Wert von "iabgpp_hdr_gppstring" in "dbabl ~ bvqqaaaaag". Es ist also ein Unterschied von nur einem Buchstaben, von "V" (nicht teilen) bis "q". Und das war's, oder vielleicht muss ich stattdessen ein einzelnes Zeichen oder eine bitgewiäre Operation überprüfen.fun isDataShareAllowed(context: Context): Boolean {
val defaultSharedPreferences = PreferenceUtil.getDefaultSharedPreferences(context)
val gppString = defaultSharedPreferences.getString("IABGPP_HDR_GppString", null) ?: return true
// DBABL~BVQVAAAAAg - don't share
// DBABL~BVQqAAAAAg - allow share
return gppString == "DBABL~BVQqAAAAAg"
}
< /code>
Die Fragen < /h2>
Geht es in OK, eine der oben erwähnten Funktionen zu verwenden, um eine der oben erwähnten Funktionen für GDPR zu verwenden? Sollte ich einfach die "755" für sie basierend auf der Website ändern? Was sollte ich für Unternehmen tun, die auf der Liste auf der Website stehen? Ist es in Ordnung, nur mit einem der Saiten zu vergleichen, wie ich es getan habe? Oder sollte ich es anders funktionieren lassen, z. B. einen einzelnen Buchstaben oder einen speziellen bitgewiären Vorgang ausführen?>