Reminder : We offer two versions of the CMP :
Xchange is free of charge, Premium is a paid version. Find out more information about the two versions here : https://appconsent.io/
-> Download the right SDK (Premium or Xchange) according to your choice, and follow the specific instructions for Xchange.
The 2.4.1 version of the SDK is available.
2.3.0 and above only supports projects that have been migrated to androidx. For more information, read Google's migration guide.
The 2.2.7 is still available, but doesn't support AndroidX.
Important! If you were using a previous version of the SDK (1.7 or earlier) you will have to create a new notice, and update some settings in your assets. Please, read this section to learn more
To add the AppConsent SDK to your Android project, follow the steps below
In your global gradle.properties
file, add the following and replace ${username}
by the provided username and ${encrypted_password}
by the provided encrypted password. Please contact us, if you don't have your ${username}
and ${encrypted_password}.
appconsent_artifactory_client_username=${username}appconsent_artifactory_client_password=${encrypted_password}
In your project build.gradle
file, under allprojects/repositories
add the following, according to the Appconsent contract you have subscribed (Premium or Xchange):
maven {url "https://artifactory.datalf.chat/artifactory/app-consent-release"credentials {username = "${appconsent_artifactory_client_username}"password = "${appconsent_artifactory_client_password}"}}
maven {url "https://artifactory.datalf.chat/artifactory/app-consent-xchange-release"credentials {username = "${appconsent_artifactory_client_username}"password = "${appconsent_artifactory_client_password}"}}
With the AppConsent Xchange SDK, a request for geoloc permission is triggered after the acquisition of the geoloc consent, if the permission is not already granted to the app.
In your application build.gradle
file, under android
add the following.
compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}configurations {all*.exclude group: 'com.google.guava', module: 'listenablefuture'}
In the dependencies, add the following and replace ${currentVersion}
.
implementation 'com.chandago.appconsentlibrary:app-consent-lib:${currentVersion}'
You may need to use MultiDexApplication
. Please follow this documentation if need it.
If you run into the following build issue: "More than one file was found with OS independent path 'META-INF/proguard/androidx-annotations.pro'", please put the following in your app build.gradle
:
android.packagingOptions {exclude 'META-INF/proguard/androidx-annotations.pro'}
You must first instantiate the SDK using your notice URL with your version ID. Read this page to get your resource URL.
import com.chandago.appconsentlibrary.*;public class SomeActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {String noticeUrl = "https://cdn.appconsent.io/<notice_path>";AppConsent appConsent = new AppConsent(this, noticeUrl);}}
Since v2.0.0 AppConsent constructor will throw an IllegalArgumentException
if noticeUrl
argument is not a valid notice url
To get the current version of the SDK you can make the following call
AppConsent.Companion.versionName();
By default the AppConsent SDK will only present a notice if the user's device is set to a GDPR country. You can chose to ignore the user's device country and display a notice anyway by adding the optional parameter ignoreCountry
of AppConsent creator as follow :
boolean ignoreCountry = true;AppConsent appConsent = new AppConsent(this, noticeUrl, ignoreCountry);
In any file where you want to use AppConsent, use the following import.
import com.chandago.appconsentlibrary.*;
import com.chandago.appconsentlibrary.*
A notice should be presented as soon as possible in the app lifecycle if the user never gave his consent.
import com.chandago.appconsentlibrary.AppConsent;public class SomeActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// ...String noticeUrl = "https://cdn.appconsent.io/<notice_path>";AppConsent appConsent = new AppConsent(this, noticeUrl);if (!appConsent.consentGiven()) {Boolean triggeredByUser = false;appConsent.presentNoticeActivity(triggeredByUser);}}}
If you callappConsent.presentNoticeActivity(triggeredByUser)
with triggeredByUser
as false
and the user already gave his consent, nothing will happen and the call will returnfalse
.
You can chose to start with a banner instead of a full screen notice.
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// ...String noticeUrl = "https://cdn.appconsent.io/<notice_path>";AppConsent appConsent = new AppConsent(this, noticeUrl);if (!appConsent.consentGiven()) {Boolean triggeredByUser = false;ViewGroup view = (ViewGroup)findViewById(R.id.mainActivity);appConsent.presentNoticeBanner(view, triggeredByUser);}}}
As for the notice, calling presentNoticeBanner
with false
will do nothing if the user already gave his consent and the call will return false
.
You can also chose to present a notice or a banner at anytime without checking the result of appConsent.consentGiven()
to force the notice (or banner) presentation, in your app settings after a user action for example.
boolean triggeredByUser = true;// present a full page noticeappConsent.presentNoticeActivity(triggeredByUser);// present a bannerappConsent.presentBanner(aViewGroup, triggeredByUser);
You can register a callback class before you present a notice or a banner. This callbacks will be called once a choice has been validated by the user.
The callback depends on your AppConsent account (Premium or Xchange), select the one you need:
appConsent.setNoticeCallback(new AppConsentNoticeCallback() {@Overridepublic void onConsentGiven() {Log.d("Callback", "Consent given");}@Overridepublic void onError(Throwable t) {Log.e("Callback", t.getMessage());}});
appConsent.setNoticeCallback(new AppConsentNoticeCallback() {@Overridepublic void onConsentGiven() {Log.d("Callback", "Consent given");if (mPreferences.getString(IABConsent.PURPOSES, "").startsWith("11111")) {appConsent.postXchangeUserInfo(new XchangeUserInfo.Builder().age(42).csp("csp").dateOfBirth("DD/MM/AAAA").email("[email protected]").externalId("externalID").firstName("firstname").household("household").revenues("00000").gender(GenderType.MALE).lastName("Lastname").phoneNumber("0000000000").xchangeInfoAddress(new XchangeInfoAddress.Builder().country("countrycode").floor("floor").postCode("Postcode").region("Region").streetName("Streetname").streetNo("Streetnumber").streetType("streettype").town("Town").build()).unstructuredData("unstructuredData").build());}}@Overridepublic void onError(Throwable t) {Log.e("Callback", t.getMessage());}});
Data is not stored and not sent if there is no acceptAll (for IAB purposes, the purpose string must start with 11111. For geoloc purposes, they must have "true" consent)
AppConsent return specific errors :
ConsentError : if an error occurred during consent
LoadingError : if an error occurred during loading notice
NoPurposeError : if you try to open notice without purpose
UnknownError : if error is unknown
As described in the IAB specification (see CMP Internal structure) the consents values are stored in SharedPreferences
with the following keys:
public static final String CONSENT_STRING = "IABConsent_ConsentString";public static final String SUBJECT_TO_GDPR = "IABConsent_SubjectToGDPR";public static final String CMP_PRESENT = "IABConsent_CMPPresent";public static final String VENDORS = "IABConsent_ParsedVendorConsents";public static final String PURPOSES = "IABConsent_ParsedPurposeConsents";
You can get them by calling the public methods as follow:
appConsent.isSubjectToGDPR());appConsent.isCmpPresentValue();appConsent.getConsentString();appConsent.getParsedPurposes();appConsent.getParsedVendors());
Or you can read the consents values for IAB vendors and purposes as follow:
SharedPreferences store = PreferenceManager.getDefaultSharedPreferences(this);String purposes = store.getString(IABConsent.PURPOSES, "");
The use of geolocation for advertising purposes is an extra sensitive matter, and AppConsent manages it through a dedicated notice and banner.
To do so you'll need to create an extra purpose in the AppConsent back-office. Once it is defined, it will appear in the notice itself, but you can prompt the user for this sole purpose through a banner or a dedicated full screen notice.
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// ...String noticeUrl = "https://cdn.appconsent.io/<notice_path>";AppConsent appConsent = new AppConsent(this, noticeUrl);boolean triggeredByUser = false;appConsent.presentGeolocationActivity(this, triggeredByUser);}}
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// ...String noticeUrl = "https://cdn.appconsent.io/<notice_path>";AppConsent appConsent = new AppConsent(this, noticeUrl);boolean triggeredByUser = false;ViewGroup view = (ViewGroup)findViewById(R.id.mainActivity);appConsent.presentGeolocationBanner(view, trigerredByUser);}}
As for standard notice and banner, you can chose to present a geolocation notice or banner at any time, which will be displayed even if an answer has been given, most likely after a user action (in your app settings for example).
boolean trigerredByUser = true;// present a full page noticeappConsent.presentGeolocationActivity(this, trigerredByUser);// present a bannerappConsent.presentGeolocationBanner(aViewGroup, trigerredByUser);
You can register a callback class which will be called when the user made his choice in the notice or banner.
appConsent.setGeolocationCallback(new AppConsentGeolocationCallback() {@Overridepublic void onResult(boolean b) {Log.d(LOG_TAG, "Geoloc answer given: " + b);}@Overridepublic void onError(Throwable throwable) {Log.e(LOG_TAG, "Geoloc error: " + throwable.getMessage());}});
You can use the SDK to read the status of the geolocation for advertising authorization.
To know if an answer has been given use the following.
AppConsent appConsent = new AppConsent(this, versionId);boolean given = appConsent.geolocationConsentGiven();
To know if the geolocation for advertising has been granted, use the following.
AppConsent appConsent = new AppConsent(this, versionId);boolean allowed = appConsent.geolocationAllowed();
For XChange users, in a non-GDPR country, the location service won't start automatically unless your application already has system location permission. If you want to be sure location service will start, you should call :
appConsent.shareUserLocation()
To know if you're in a GDPR country or not, you should call :
appConsent.isSubjectToGDPR();
If you already collected consents about geolocation for advertising before using AppConsent for Android, you can set those consents directly.
AppConsent appConsent = new AppConsent(this, versionId);Map<String, Boolean> map = new HashMap<>();map.put("359fFyR", true);map.put("JU7iLdm", true);appConsent.setGeolocPurposesAuthorization(this, map, new AppConsentSetGeolocationPurposeCallback() {@Overridepublic void onSuccess() {appConsent.presentNoticeActivity(false);}@Overridepublic void onError(Throwable t) {Log.e("SetGeolocation", t.getMessage(), t);}});
If you want to present notice activity or banner after setting previously collected consent, please wait onSuccess callback before calling presentNoticeActivity()
like in previous example.
Since you can update your notice information in the AppConsent back-office, the consents collected before the updated could also need to be updated.
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// ...String noticeUrl = "https://cdn.appconsent.io/<notice_path>";AppConsent appConsent = new AppConsent(this, noticeUrl);// check for updatesappConsent.checkForUpdate(new AppConsentUpdateCallback() {@Overridepublic void onResult(boolean updated) {if (updated) {appConsent.presentNoticeActivity(false);}}@Overridepublic void onError(Throwable t) {// ...}});}}
If your notice is linked to the Global Vendor List, you can limit the number of vendors displayed in your notice.
To do so, add pubVendors json in the Configuration view of your notice on the Back Office as following
{"publisherVendorsVersion": 1,"globalVendorListVersion": 42,"updatedAt": "2018-10-15T00:00:00Z","vendors": [{"id": 124}]}
If the AppConsent back-office lets you define your own extra purposes, you can also define extra vendors, to be attached to those purposes.
To do so, add extraVendors json in the Configuration view of your notice on the Back Office as following
To link the vendors defined in the file with your extra purpose, you'll need to know the id of your extra purposes. You can find it in the gvl file : https://vendorlist.consensu.org/v-XXX/vendorlist.json (replace XXX by your GVL number version), or ask your SFBX representative.
"vendorListVersion":1,"lastUpdated":"2018-10-15T00:00:00Z","extraVendors": [{// This one comes from the GVL"id": "IdFromGvl","name": "My Vendor","policyUrl": "https://some.policy-url.com","extraPurposeIds": ["purposeId"]},{// This one does not come from the GVL, its id is its name"id": "My other vendor","name": "My other vendor","policyUrl": "https://some.other-policy-url.com","extraPurposeIds": ["purposeId"]},{// This one does will not have a switch button, but the switch will be exposed for the global purpose"id": "My other vendor","name": "My other vendor","policyUrl": "https://some.other-policy-url.com","notConsentablePurposeIds": ["purposeId"]}]}
If you use notConsentablePurposeIds
, the vendors will not have any switch and the purpose will be exposed like the capture bellow. The consent is propagated for all vendors.
Read this section for more information.
Given the id of an extra purpose and an extra vendors, you can read there authorization status using the following code:
boolean purposeAllowed = appConsent.extraPurposeAllowed("purpose-id");boolean vendorAllowed = appConsent.extraVendorAllowedInExtraPurpose("vendor-id", "purpose-id");
You can use Huq SDK which is integrated in AppConsent Xchange. For more information about Huq please visit https://huq.io/.
For sake of clarity, Huq sdk is not integrated in the Premium SDK
To start Huq in AppConsent Xchange :
appConsent.startHuq()
To stop Huq :
appConsent.stopHuq()
Huq will start when user will give geolocation consent and allow location permissions on his device. And it will stop if user revoke his geolocation consents.
Your notice can work offline. To do so, you need to add two files locally in your application assets: notice.json
and gvl.json
.
The content of the notice and the version of the GVL must match the ones configured in the AppConsent back-office.
To get the content of your notice.json
file, follow the link of your notice resource url in the Back Office
Get the content of your notice and save it locally in your application's assets folder.
{"accountID": number,"buildID": number,"gvlVersion": number,"extraVendorsList": {},"pubVendors": {},"noticeID": number,"sourceID": number,"versionID": string,"scope": string,"purposes": [],"customisations": {}}
Get the gvlVersion
from notice.json
.
Get the content of https://vendorlist.consensu.org/v-<gvlVersion>/vendorlist.json
and save it locally in your application's assets folder.
To have a notice which fits with your app UI, you can customize visuals, texts and colors using the backoffice. Read this page for more information.
You can also customize other settings if needed:
Customize CSS
<style name="SdkTheme" parent="Theme.AppCompat.Light.NoActionBar"><!-- Customize your theme here. --><item name="colorPrimary">@color/colorPrimary</item><item name="colorPrimaryDark">@color/colorPrimaryDark</item><item name="colorAccent">@color/colorAccent</item><item name="android:windowFullscreen">true</item><item name="android:textColorPrimary">@android:color/white</item><item name="android:textColorSecondary">@android:color/white</item><item name="actionMenuTextColor">@android:color/white</item></style>
Override the SDK Theme
Using the AppConsentTheme
class and its builder
, you can also override the SDK theme for the following customizations.
For the offline notice, you will need to customize the visuals assets. If set, the images you set locally in your application will be used if there is no customization in the backoffice, or as a fallback in case of network failure (offline).
// Create the builderAppConsentTheme.Builder builder = new AppConsentTheme.Builder(context)// override sdk theme.theme(R.style.SdkTheme)// Icon on top-left corner on onboarding and success pages.iconDrawable(getDrawable(R.drawable.myIcon)).onboardingImage(getDrawable(R.drawable.someDrawable)).noticeSuccessImage(getDrawable(R.drawable.someDrawable))// Icon before each notice information item.noticeInformationIcon(getDrawable(R.drawable.someDrawable))// Icon geolocation advertising.geoAdvertisigIcon(getDrawable(R.drawable.someDrawable))// Text Introduction IAB Title.introductionTitle(getString(R.string.someText))// UI in a single step with CTA scrolling.singleStepCtaScrolling(true)// Display Big Image in Geolocation Notice.displayBigGeolocationImage(true)// UI geolocation cta scrolling.geolocationCtaScrolling(true);// Build it to create the theme objectAppConsentTheme theme = builder.build();// Attach it when initalizing AppConsentAppConsent appConsent = new AppConsent(context, "notice_url", theme);
If you need to add clickable links in your texts, use methods passing string ressources like exemple below:
AppConsentTheme theme = new AppConsentTheme.Builder(this).onboardingDetailsText(R.string.text_with_link).onboardingConclusionText(R.string.text_with_link).geoNoticeIntroductionText(R.string.text_with_link).geoNoticeDetailsText(R.string.text_with_link).build();AppConsent appConsent = new AppConsent(this, "notice_url", theme);
<resources><string name="text_with_link">Voici la <a href="https://www.sfbx.io/">Charte de confidentialité</a></string></resources>
When a consent is given, the SDK writes the IAB consent string informations in SharedPreferences
. Please refer to the IAB documentation to read more about that, especially for what's written in SharedPreferences
and how to use it.
Read the IAB Documentation
If you are using the version 1.7 or earlier, and want to update the SDK with a newer version, you will need to create a new source in the backoffice and update your existing assets in your application. Here is the procedure to follow:
Since the version 2.0.0, you need to have a notice, specific to your Mobile App Android, linked to a source with a bundle ID (instead of a target url).
To do so , you need to : 1) Create a new source. This source needs to have a "Mobile app" type and a bundle ID. See the section Quick Start in order to learn how to create a Source with a bundle ID.
2) Create a new notice for your Mobile App Android : see this section to learn how to create a notice for mobile app.
Once your new notice is created and the SDK updated, you need to replace the "resource url" with the new one in your application. Read this page to learn how to get your resource url.
For the offline version of your notice, you need to update your assets files:
Update the file "notice.json" :
Open the resource url of your notice in your browser, and copy-paste the code in your notice.json file.
In this notice.json file, delete all the images links (if you have some):
Update the images files in the builder: If your notice is customized with some images, you need to define this images in the builder for the offline version. Read this page for more information.
Update your GVL.json file: Make sure that your online notice and your offline notice have the same GVL number version.
(You can find the number of the GVL, in your notice form, in the backoffice)
If not, you need to update the GVL.json file in your assets: copy paste the information from this link : https://vendorlist.consensu.org/v-NUMBER_OF_YOUR_GVL/vendorlist.json
Delete this two files in your assets: Pubvendros.json and ExtravendorList.json Now, the information of this two files is in the notice.json file.