好吧,所以我最终实现了我自己的同意机制。我认为它符合要求,所以为了其他人的利益,这里是:
首先,声明这些变量。这些将用于决定您是否需要出示同意书:
boolean shouldShowConsentForm = false;
boolean goAdFreeChosen = false; // to prevent firing the consent dialog when going into settings.
使用此方法告诉用户您将请求同意:
void showConsentDialogIntro(final Context context) {
Bundle params = new Bundle();
params.putString("what", "showConsentDialogIntro");
mFirebaseAnalytics.logEvent(CONSENT_COLLECTION, params);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Something important before you continue...").
setMessage("This app is kept free by showing ads. Tap next to see privacy options regarding this.\n\n(You can change this later in Settings too)").
setPositiveButton("Next", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
showYesNoDialog(context, true);
}
})
//.setNegativeButton("Cancel", null)
.show();
}
private void showYesNoDialog(final Context context, boolean shouldReportInFirebase) {
if (shouldReportInFirebase) {
Bundle params = new Bundle();
params.putString("what", "showYesNoDialog");
mFirebaseAnalytics.logEvent(CONSENT_COLLECTION, params);
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
final CharSequence[] items = {"Yes - Shows relevant ads", "No - Shows less relevant ads", "Go Ad free",
"Learn how our partners collect and use your data"};
builder.setTitle("Can THIS_APP_NAME use your data to tailor ads for you?").
setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Bundle params = new Bundle();
switch (which) {
case 0: // yes
ConsentInformation.getInstance(context)
.setConsentStatus(ConsentStatus.PERSONALIZED);
shouldShowConsentForm = false;
mInterstitialAd.loadAd(new AdRequest.Builder()
.addTestDevice(TEST_DEVICE_FOR_ADS)
.build());
params.putString("what", "yes");
break;
case 1: // no
ConsentInformation.getInstance(context)
.setConsentStatus(ConsentStatus.NON_PERSONALIZED);
shouldShowConsentForm = false;
Bundle extras = new Bundle();
extras.putString("npa", "1");
mInterstitialAd.loadAd(new AdRequest.Builder()
.addNetworkExtrasBundle(AdMobAdapter.class, extras)
.addTestDevice(TEST_DEVICE_FOR_ADS)
.build());
params.putString("what", "no");
Snackbar.make(myToolbar, "We'll partner with Google and use a unique identifier to respect your choice.",
Snackbar.LENGTH_LONG).addCallback(new BaseTransientBottomBar.BaseCallback<Snackbar>() {
@Override
public void onDismissed(Snackbar transientBottomBar, int event) {
super.onDismissed(transientBottomBar, event);
Snackbar.make(myToolbar, "You can change your choice later in Settings.", Snackbar.LENGTH_LONG).show();
}
})
//.setDuration(3500)
.show(); // 3500 is perhaps the duration for LENGTH_LONG.
/*
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Snackbar.make(myToolbar, "You can change your choice later in Settings.", Snackbar.LENGTH_LONG).show();
}
}, 3500);
*/
break;
case 2: // ad free
// drawer.setSelection(settings, true);
goAdFreeChosen = true;
drawer.setSelection(DRAWER_IDENTIFIER_SETTINGS, true);
params.putString("what", "ad_free");
break;
case 3: // learn more
showLearnMoreDialog(context);
params.putString("what", "showLearnMoreDialog");
break;
}
mFirebaseAnalytics.logEvent(CONSENT_COLLECTION, params);
}
})
// .setNegativeButton("Cancel", null)
.show();
}
如果用户点击了解更多(上面菜单中的第4个选项),他们将看到所有提供商的列表,他们可以点击查看各自的隐私政策:
private void showLearnMoreDialog(final Context context) {
List<AdProvider> adProviders =
ConsentInformation.getInstance(context).getAdProviders();
final CharSequence[] itemsName = new CharSequence[adProviders.size()];
final String[] itemsURL = new String[adProviders.size()];
int i = 0;
for (AdProvider adProvider : adProviders) {
itemsName[i] = adProvider.getName();
itemsURL[i] = adProvider.getPrivacyPolicyUrlString();
i++;
}
ArrayAdapter adapter = new ArrayAdapter<>(context,
android.R.layout.simple_list_item_1, itemsName);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Tap on our partners to learn more about their privacy policies")
.setNegativeButton("Back", null)
.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
/* Toast.makeText(context,
"URL: " + itemsURL[which].toExternalForm(), Toast.LENGTH_SHORT).show();*/
Intent browserIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse(itemsURL[which]));
startActivity(browserIntent);
Bundle params = new Bundle();
params.putString("what", "showLearnMoreDialog_open_privacy_policy");
mFirebaseAnalytics.logEvent(CONSENT_COLLECTION, params);
}
})
.setCancelable(true)
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
showYesNoDialog(context, false);
}
})
.show();
}
请注意,我也在本文中实现了firebase分析,但是如果您不想记录这些事件,可以删除与“params”相关的行。
您可以使用此方法查看同意状态:
private void getConsentStatusAndLoadAdAccordingly(final Context context) {
ConsentInformation consentInformation = ConsentInformation.getInstance(context);
// consentInformation.addTestDevice(TEST_DEVICE_FOR_ADS);
// consentInformation.setDebugGeography(DebugGeography.DEBUG_GEOGRAPHY_EEA); // for forcing Europe area; testing.
// consentInformation.setConsentStatus(ConsentStatus.UNKNOWN); // useful for triggering it after saving status; testing.
String[] publisherIds = {MY_PUBLISHER_ID};
consentInformation.requestConsentInfoUpdate(publisherIds, new ConsentInfoUpdateListener() {
@Override
public void onConsentInfoUpdated(ConsentStatus consentStatus) {
loog("consentInformation", "onConsentInfoUpdated");
// User's consent status successfully updated.
if (ConsentInformation.getInstance(context).isRequestLocationInEeaOrUnknown()) {
loog("consentInformation", "isRequestLocationInEeaOrUnknown = true");
/* If the isRequestLocationInEeaOrUnknown() method returns false, the user is not
located in the European Economic Area and consent is not required under the EU User Consent Policy.
If the isRequestLocationInEeaOrUnknown() method returns true:
If the returned ConsentStatus is PERSONALIZED or NON_PERSONALIZED, the user has already provided consent.
You can now forward consent to the Google Mobile Ads SDK.
If the returned ConsentStatus is UNKNOWN, you need to collect consent. */
loog("consentInformation", "consentStatus = " + consentStatus);
if (consentStatus == ConsentStatus.UNKNOWN) {
// showGoogleConsentForm(DrawerAndFragmentActivity.this);
shouldShowConsentForm = true;
} else if (consentStatus == ConsentStatus.NON_PERSONALIZED) {
/* The default behavior of the Google Mobile Ads SDK is to serve personalized ads. If a user
has consented to receive only non-personalized ads, you can configure an AdRequest object
with the following code to specify that only non-personalized ads should be returned: */
Bundle extras = new Bundle();
extras.putString("npa", "1");
mInterstitialAd.loadAd(new AdRequest.Builder()
.addNetworkExtrasBundle(AdMobAdapter.class, extras)
.addTestDevice(TEST_DEVICE_FOR_ADS)
.build());
} else if (consentStatus == ConsentStatus.PERSONALIZED) {
mInterstitialAd.loadAd(new AdRequest.Builder()
.addTestDevice(TEST_DEVICE_FOR_ADS)
.build());
}
} else {
loog("consentInformation", "isRequestLocationInEeaOrUnknown = false");
mInterstitialAd.loadAd(new AdRequest.Builder()
.addTestDevice(TEST_DEVICE_FOR_ADS)
.build());
}
}
@Override
public void onFailedToUpdateConsentInfo(String errorDescription) {
// User's consent status failed to update.
loog("consentInformation", "onFailedToUpdateConsentInfo: errorDescription = " + errorDescription);
mInterstitialAd.loadAd(new AdRequest.Builder()
.addTestDevice(TEST_DEVICE_FOR_ADS)
.build());
}
});
}
最后,当您需要决定是显示广告还是显示同意书时,可以使用如下逻辑:(shouldShowAd是一个可选的布尔值,为了更清楚起见,我想把它放进去)
if (shouldShowAd) {
if (shouldShowConsentForm) {
if (!goAdFreeChosen)
showConsentDialogIntro(DrawerAndFragmentActivity.this);
goAdFreeChosen = false;
} else {
if (mInterstitialAd != null)
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
}
}
}