Skip to content

Instantly share code, notes, and snippets.

@Josuhu
Last active October 27, 2023 13:45
Show Gist options
  • Save Josuhu/39194bcd5e6b0b14120c3e2e47613031 to your computer and use it in GitHub Desktop.
Save Josuhu/39194bcd5e6b0b14120c3e2e47613031 to your computer and use it in GitHub Desktop.
Java classes for GDPR consent
// TODO For implementation see coding video series https://youtube.com/playlist?list=PLQVB-tSJSr656zCJoViyF3MYlKGljVTT7&si=4xY8dV7XkrV_7f1f
public class JavaConsentTracker {
private static final String TAG = "ConsentTracker";
private final MyLogging myLogger = new MyLogging(); // TODO Log with your own logger
private final Context context;
public JavaConsentTracker(Context context) {
this.context = context;
}
public boolean isUserConsentValid() {
boolean isGdpr = isGDPR();
boolean canShowPersAds = canShowPersonalizedAds();
boolean canShowAds = canShowAds();
boolean consentValidity = !isGdpr || canShowPersAds || canShowAds;
myLogger.logThis(TAG, "isUserConsentValid: " + consentValidity + ", GDPR: " + isGdpr +
", PersAds: " + canShowPersAds + ", Ads: " + canShowAds, Log.DEBUG);
return consentValidity;
}
private boolean isGDPR() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
int gdpr = prefs.getInt("IABTCF_gdprApplies", 0);
return gdpr == 1;
}
private boolean canShowAds() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String purposeConsent = prefs.getString("IABTCF_PurposeConsents", "");
String vendorConsent = prefs.getString("IABTCF_VendorConsents", "");
String vendorLI = prefs.getString("IABTCF_VendorLegitimateInterests", "");
String purposeLI = prefs.getString("IABTCF_PurposeLegitimateInterests", "");
int googleId = 755;
boolean hasGoogleVendorConsent = hasAttribute(vendorConsent, googleId);
boolean hasGoogleVendorLI = hasAttribute(vendorLI, googleId);
// Minimum required for at least non-personalized ads
return hasConsentFor(Collections.singletonList(1), purposeConsent, hasGoogleVendorConsent)
&& hasConsentOrLegitimateInterestFor(Arrays.asList(2, 7, 9, 10), purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI);
}
private boolean canShowPersonalizedAds() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String purposeConsent = prefs.getString("IABTCF_PurposeConsents", "");
String vendorConsent = prefs.getString("IABTCF_VendorConsents", "");
String vendorLI = prefs.getString("IABTCF_VendorLegitimateInterests", "");
String purposeLI = prefs.getString("IABTCF_PurposeLegitimateInterests", "");
int googleId = 755;
boolean hasGoogleVendorConsent = hasAttribute(vendorConsent, googleId);
boolean hasGoogleVendorLI = hasAttribute(vendorLI, googleId);
return hasConsentFor(Arrays.asList(1, 3, 4), purposeConsent, hasGoogleVendorConsent)
&& hasConsentOrLegitimateInterestFor(Arrays.asList(2, 7, 9, 10), purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI);
}
// Check if a binary string has a "1" at position "index" (1-based)
private boolean hasAttribute(String input, int index) {
return input.length() >= index && input.charAt(index - 1) == '1';
}
// Check if consent is given for a list of purposes
private boolean hasConsentFor(
List<Integer> purposes,
String purposeConsent,
boolean hasVendorConsent
) {
for (int p : purposes) {
if (!hasAttribute(purposeConsent, p)) {
return false;
}
}
return hasVendorConsent;
}
// Check if a vendor either has consent or legitimate interest for a list of purposes
private boolean hasConsentOrLegitimateInterestFor(
List<Integer> purposes,
String purposeConsent,
String purposeLI,
boolean hasVendorConsent,
boolean hasVendorLI
) {
for (int p : purposes) {
if ((hasAttribute(purposeLI, p) && hasVendorLI) || (hasAttribute(purposeConsent, p) && hasVendorConsent)) {
continue;
} else {
return false;
}
}
return true;
}
}
// TODO For implementation see coding video series https://youtube.com/playlist?list=PLQVB-tSJSr656zCJoViyF3MYlKGljVTT7&si=4xY8dV7XkrV_7f1f
public class JavaGdpr {
private static final String TAG = "MyGdpr";
private final MyLogging myLogging = new MyLogging(); // TODO Log with your own logger
private final ConsentInformation consentInformation;
private ConsentForm consentForm;
private final MyToasts myToasts; // TODO Toast with your own toaster
private final Context context;
public JavaGdpr(Context context) {
this.context = context;
consentInformation = UserMessagingPlatform.getConsentInformation(context);
myToasts = new MyToasts(context);
}
/**IN PRODUCTION CALL AT ONCREATE FOR CONSENT FORM CHECK*/
public void updateConsentInfo(
Activity activity,
boolean underAge,
MainViewModel viewModel,
JavaConsentTracker consentTracker,
Runnable initAds
) {
ConsentRequestParameters params = new ConsentRequestParameters.Builder()
.setTagForUnderAgeOfConsent(underAge)
.build();
requestConsentInfoUpdate(activity, params, viewModel, consentTracker, initAds);
}
/**ONLY TO DEBUG EU & NONE EU GEOGRAPHICS
* EU: ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA
* NOT EU: ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_NOT_EEA
* DISABLED: ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_DISABLED
* requestConsentInfoUpdate() logs the hashed id when run*/
public void updateConsentInfoWithDebugGeographics(
Activity activity,
int geography,
MainViewModel viewModel,
JavaConsentTracker consentTracker,
Runnable initAds
) {
ConsentDebugSettings debugSettings = new ConsentDebugSettings.Builder(context)
.setDebugGeography(geography)
.addTestDeviceHashedId(/*TODO hashId string here*/) // TODO insert your test devices hashId
.build();
ConsentRequestParameters params = new ConsentRequestParameters.Builder()
.setConsentDebugSettings(debugSettings)
.build();
requestConsentInfoUpdate(activity, params, viewModel, consentTracker, initAds);
}
private void requestConsentInfoUpdate(
Activity activity,
ConsentRequestParameters params,
MainViewModel viewModel,
JavaConsentTracker consentTracker,
Runnable initAds
) {
consentInformation.requestConsentInfoUpdate(activity, params, () -> {
if (consentInformation.isConsentFormAvailable()) {
loadForm(activity, viewModel, consentTracker, initAds);
} else {
viewModel.getConsentPermit().setValue(isConsentObtained(consentTracker));
}
},
formError -> myLogging.logThis(TAG, "requestConsentInfoUpdate: " + formError.getMessage(), Log.ERROR)
);
}
private void loadForm(
Activity activity,
MainViewModel viewModel,
JavaConsentTracker consentTracker,
Runnable initAds
) {
UserMessagingPlatform.loadConsentForm(context,
consentForm -> {
this.consentForm = consentForm;
if (consentInformation.getConsentStatus() == REQUIRED) {
myLogging.logThis(TAG, "consentForm is required to show", Log.DEBUG);
consentForm.show(activity, formError -> {
if (formError != null) {
myLogging.logThis(TAG, "consentForm show " + formError.getMessage(), Log.ERROR);
}
if (consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.OBTAINED) {
myLogging.logThis(TAG, "consentForm is Obtained", Log.DEBUG);
viewModel.getConsentPermit().setValue(isConsentObtained(consentTracker));
initAds.run();
}
loadForm(activity, viewModel, consentTracker, initAds);
});
} else {
viewModel.getConsentPermit().setValue(isConsentObtained(consentTracker));
}
},
formError -> myLogging.logThis(TAG, "loadForm Failure: " + formError.getMessage(), Log.ERROR)
);
}
/**RETURNS TRUE IF EU/UK IS TRULY OBTAINED OR NOT REQUIRED ELSE FALSE*/
public void reUseExistingConsentForm(
Activity activity,
MainViewModel viewModel,
JavaConsentTracker consentTracker,
Runnable initAds
) {
if (consentInformation.isConsentFormAvailable()) {
myLogging.logThis(TAG, "reUseExistingConsentForm", Log.DEBUG);
consentForm.show(activity, formError -> {
if (formError != null) {
myLogging.logThis(TAG, "consentForm show " + formError.getMessage(), Log.ERROR);
}
if (consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.OBTAINED) {
myLogging.logThis(TAG, "consentForm is Obtained", Log.DEBUG);
viewModel.getConsentPermit().setValue(isConsentObtained(consentTracker));
initAds.run();
}
loadForm(activity, viewModel, consentTracker, initAds);
});
} else {
myToasts.toastText("Consent form not available, check internet connection.", Toast.LENGTH_SHORT);
viewModel.getConsentPermit().setValue(isConsentObtained(consentTracker));
}
}
private boolean isConsentObtained(JavaConsentTracker consentTracker) {
boolean obtained = consentTracker.isUserConsentValid() && consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.OBTAINED;
boolean notRequired = consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.NOT_REQUIRED;
boolean isObtained = obtained || notRequired;
myLogging.logThis(TAG, "isConsentObtained or not required: " + isObtained, Log.DEBUG);
return isObtained;
}
/**RESET ONLY IF TRULY REQUIRED. E.G FOR TESTING OR USER WANTS TO RESET CONSENT SETTINGS*/
public void resetConsent() {
consentInformation.reset();
}
}
@Josuhu
Copy link
Author

Josuhu commented Oct 27, 2023

For implementation in to Activity, see coding video series https://youtube.com/playlist?list=PLQVB-tSJSr656zCJoViyF3MYlKGljVTT7&si=4xY8dV7XkrV_7f1f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment