Android,即使用户不同意或用户关闭表单,UMP 也始终返回“OBTAINED”。 所以很难用它做任何事情。我想知道用户是否不同意,在这种情况下关闭应用程序。然后下次打开应用程序时,应该立即显示表单。然而,另一个问题是,当用户在表单中选择内容并批准同意时,下次再次打开表单时,设置将被重置(就像表单从未保存过一样)。另一个问题是,用户几乎不可能选择正确的内容来获取广告,并且在大多数情况下,用户将获得一个没有任何广告的免费应用程序(因为 OBTAINED 状态并不能说明用户是否同意)。另外,我无法获取用户选择的内容(我真的需要查看共享首选项才能获取该信息吗?总体而言,这个 UMP 似乎工作得很奇怪,或者也许我实现了错误?也许很快就会发布任何改进使用实现 'com.google.android.ump:user-messaging-platform:2.1.0'
此外,如果用户已经同意,并且 Admob 设置从我的应用程序的个人广告更改为非个人广告,那么用户仍然会收到个人广告。
这是代码:
ConsentRequestParameters params = new ConsentRequestParameters
.Builder()
.setTagForUnderAgeOfConsent(false)
.build();
ConsentInformation consentInformation;
consentInformation = UserMessagingPlatform.getConsentInformation(this.getApplicationContext());
consentInformation.requestConsentInfoUpdate(
(Activity) this,
params,
new ConsentInformation.OnConsentInfoUpdateSuccessListener() {
@Override
public void onConsentInfoUpdateSuccess() {
// The consent information state was updated.
// You are now ready to check if a form is available.
if (consentInformation.isConsentFormAvailable()) {
// Loads a consent form. Must be called on the main thread.
UserMessagingPlatform.loadConsentForm(
MyActivity.this.getApplicationContext(),
new UserMessagingPlatform.OnConsentFormLoadSuccessListener() {
@Override
public void onConsentFormLoadSuccess(ConsentForm consentForm) {
consentForm.show(
(Activity) MyActivity.this,
new ConsentForm.OnConsentFormDismissedListener() {
@Override
public void onConsentFormDismissed(@Nullable FormError formError) {
// TODO: Always getting "OBTAINED" even if user dismissed form or selected to not consent.
// User did not consent so consentStatus is still REQUIRED
if (consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.REQUIRED) {
MyActivity.this.finish();
}
}
});
}
},
new UserMessagingPlatform.OnConsentFormLoadFailureListener() {
@Override
public void onConsentFormLoadFailure(FormError formError) {
// Handle Error.
}
}
);
} else {
// Handle error
}
}
},
new ConsentInformation.OnConsentInfoUpdateFailureListener() {
@Override
public void onConsentInfoUpdateFailure(FormError formError) {
// Handle the error.
}
});
我尝试过以各种方式更改代码,但仍然遇到相同的问题。所以现在我在 Admob 设置中选择了非个人广告,因为 UMP 似乎不起作用。
在 Google 一周毫无进展之后...他们的哲学似乎是故意将 AdMob 变成垃圾箱大火(不同意“合法利益”不是问题!)...我已经决定了我的临时解决方案,直到他们希望有一天能够齐心协力。
总之我是...
如果流输出“无广告”,那么当他们到达主页时,我会向他们显示一个对话框,解释为什么某些功能被禁用并邀请他们重新提交同意选项。
这当然是一种可怕的用户体验...输入一堆神秘的同意选项只是在主页上被拒绝并被告知再次这样做,因为他们选择的组合是错误的...但这似乎就是用户体验谷歌想要。
要么他们认真地期望我们支持不同意用户的费用,而没有任何手段将他们货币化!
以下是我的解析器类,以防有人想遵循类似的方法(我是一名 flutter 开发人员,但我知道 dart 与 JavaScript 没有什么不同)。
import 'dart:async';
import 'package:buck_the_critics/enums.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:iabtcf_consent_info/iabtcf_consent_info.dart';
class AdmobConsentParser {
// User must consent to these for any ads at all
List < DataUsagePurpose > consentsRequiredForAds = [
DataUsagePurpose.storeAndAccessInformationOnADevice // 1
];
// User must consent to these for targetted ads
List < DataUsagePurpose > consentsRequiredForTargettedAds = [
DataUsagePurpose.storeAndAccessInformationOnADevice, // 1
DataUsagePurpose.createAPersonalisedAdsProfile, // 3
DataUsagePurpose.selectPersonalisedAds, // 4
];
// User must either consent or NOT untoggle legitimate interest for any of these for any ads at all
List < DataUsagePurpose > usagesRequiringConsentOrLegitimateInterest = [
DataUsagePurpose.selectBasicAds, // 2
DataUsagePurpose.measureAdPerformance, // 7
DataUsagePurpose.applyMarketResearchToGenerateAudienceInsights, // 9
DataUsagePurpose.developAndImproveProducts // 10
];
Future < AdConsent > getAdConsentLevel(BasicConsentInfo ? usersConsent) async {
if (usersConsent != null && usersConsent is ConsentInfo) {
final gdprApplies = isGDPR(usersConsent);
if (gdprApplies == true) {
final targetedAds = await canShowPersonalizedAds(usersConsent);
if (targetedAds != null && targetedAds) {
return AdConsent.targeted;
} else {
final untargetedAds = await canShowAds(usersConsent);
if (untargetedAds != null && untargetedAds) {
return AdConsent.untargeted;
} else {
return AdConsent.none;
}
}
} else {
return AdConsent.none;
}
} else {
return AdConsent.targeted;
}
}
bool ? isGDPR(BasicConsentInfo ? usersConsent) {
return usersConsent ? .gdprApplies;
}
// 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
Future < bool ? > canShowAds(ConsentInfo usersConsent) async {
final hasConsent = _hasConsent(usersConsent, consentsRequiredForAds);
final hasConsentOrLegitimateInterest = _hasConsentOrLegitimateInterest(
usersConsent, usagesRequiringConsentOrLegitimateInterest);
return hasConsent && hasConsentOrLegitimateInterest;
}
// 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
Future < bool ? > canShowPersonalizedAds(ConsentInfo usersConsent) async {
return _hasConsent(usersConsent, consentsRequiredForTargettedAds) &&
_hasConsentOrLegitimateInterest(
usersConsent, usagesRequiringConsentOrLegitimateInterest);
}
_hasConsent(
ConsentInfo usersConsent, List < DataUsagePurpose > requiredConsents) {
return requiredConsents
.every((purpose) => usersConsent.purposeConsents.contains(purpose));
}
_hasConsentOrLegitimateInterest(ConsentInfo usersConsent,
List < DataUsagePurpose > requiredLegitimateInterests) {
return requiredLegitimateInterests.every((purpose) =>
usersConsent.purposeConsents.contains(purpose) ||
usersConsent.purposeLegitimateInterests.contains(purpose));
}
}
final admobConsentParserProvider = Provider.autoDispose((ref) {
return AdmobConsentParser();
});
final adConsentLevelProvider = StreamProvider.autoDispose < AdConsent > ((ref) {
final controller = StreamController < AdConsent > ();
final consentParser = ref.watch(admobConsentParserProvider);
IabtcfConsentInfo.instance.consentInfo().listen((event) async {
final consentLevel = await consentParser.getAdConsentLevel(event);
controller.sink.add(consentLevel);
});
return controller.stream;
});
import 'dart:async';
import 'package:buck_the_critics/enums.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:iabtcf_consent_info/iabtcf_consent_info.dart';
class AdmobConsentParser {
// User must consent to these for any ads at all
List < DataUsagePurpose > consentsRequiredForAds = [
DataUsagePurpose.storeAndAccessInformationOnADevice // 1
];
// User must consent to these for targetted ads
List < DataUsagePurpose > consentsRequiredForTargettedAds = [
DataUsagePurpose.storeAndAccessInformationOnADevice, // 1
DataUsagePurpose.createAPersonalisedAdsProfile, // 3
DataUsagePurpose.selectPersonalisedAds, // 4
];
// User must either consent or NOT untoggle legitimate interest for any of these for any ads at all
List < DataUsagePurpose > usagesRequiringConsentOrLegitimateInterest = [
DataUsagePurpose.selectBasicAds, // 2
DataUsagePurpose.measureAdPerformance, // 7
DataUsagePurpose.applyMarketResearchToGenerateAudienceInsights, // 9
DataUsagePurpose.developAndImproveProducts // 10
];
Future < AdConsent > getAdConsentLevel(BasicConsentInfo ? usersConsent) async {
if (usersConsent != null && usersConsent is ConsentInfo) {
final gdprApplies = isGDPR(usersConsent);
if (gdprApplies == true) {
final targetedAds = await canShowPersonalizedAds(usersConsent);
if (targetedAds != null && targetedAds) {
return AdConsent.targeted;
} else {
final untargetedAds = await canShowAds(usersConsent);
if (untargetedAds != null && untargetedAds) {
return AdConsent.untargeted;
} else {
return AdConsent.none;
}
}
} else {
return AdConsent.none;
}
} else {
return AdConsent.targeted;
}
}
bool ? isGDPR(BasicConsentInfo ? usersConsent) {
return usersConsent ? .gdprApplies;
}
// 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
Future < bool ? > canShowAds(ConsentInfo usersConsent) async {
final hasConsent = _hasConsent(usersConsent, consentsRequiredForAds);
final hasConsentOrLegitimateInterest = _hasConsentOrLegitimateInterest(
usersConsent, usagesRequiringConsentOrLegitimateInterest);
return hasConsent && hasConsentOrLegitimateInterest;
}
// 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
Future < bool ? > canShowPersonalizedAds(ConsentInfo usersConsent) async {
return _hasConsent(usersConsent, consentsRequiredForTargettedAds) &&
_hasConsentOrLegitimateInterest(
usersConsent, usagesRequiringConsentOrLegitimateInterest);
}
_hasConsent(
ConsentInfo usersConsent, List < DataUsagePurpose > requiredConsents) {
return requiredConsents
.every((purpose) => usersConsent.purposeConsents.contains(purpose));
}
_hasConsentOrLegitimateInterest(ConsentInfo usersConsent,
List < DataUsagePurpose > requiredLegitimateInterests) {
return requiredLegitimateInterests.every((purpose) =>
usersConsent.purposeConsents.contains(purpose) ||
usersConsent.purposeLegitimateInterests.contains(purpose));
}
}
final admobConsentParserProvider = Provider.autoDispose((ref) {
return AdmobConsentParser();
});
final adConsentLevelProvider = StreamProvider.autoDispose < AdConsent > ((ref) {
final controller = StreamController < AdConsent > ();
final consentParser = ref.watch(admobConsentParserProvider);
IabtcfConsentInfo.instance.consentInfo().listen((event) async {
final consentLevel = await consentParser.getAdConsentLevel(event);
controller.sink.add(consentLevel);
});
return controller.stream;
});