Android TCF V1[ DEPRECATED ]

This page describes how to add the AppConsent SDK in your Android application.

Adding AppConsent to your application

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.

Download

The 2.3.17 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

Setup

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):

Premium
Xchange (Free)
Premium

maven {
url "https://artifactory.datalf.chat/artifactory/app-consent-release"
credentials {
username = "${appconsent_artifactory_client_username}"
password = "${appconsent_artifactory_client_password}"
}
}
Xchange (Free)

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_8
targetCompatibility 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'
}

Using AppConsent

Start AppConsent

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 {
@Override
protected 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();

Managing the user's country

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);

Presenting a notice

Import AppConsent

In any file where you want to use AppConsent, use the following import.

Java
Kotlin
Java
import com.chandago.appconsentlibrary.*;
Kotlin
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 {
@Override
protected 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.

Start with a banner instead of a notice

You can chose to start with a banner instead of a full screen notice.

public class MainActivity extends AppCompatActivity {
@Override
protected 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.

Presenting on user demand

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 notice
appConsent.presentNoticeActivity(triggeredByUser);
// present a banner
appConsent.presentBanner(aViewGroup, triggeredByUser);

Notice and banner callback

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:

Premium Account
Xchange Account
Premium Account

appConsent.setNoticeCallback(new AppConsentNoticeCallback() {
@Override
public void onConsentGiven() {
Log.d("Callback", "Consent given");
}
@Override
public void onError(Throwable t) {
Log.e("Callback", t.getMessage());
}
});
Xchange Account

appConsent.setNoticeCallback(new AppConsentNoticeCallback() {
                @Override
                public 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());
                    }
                }
                @Override
                public 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

Reading consents values

As described in the IAB specification (see CMP Internal structure) the consents values are stored in SharedPreferences with the following keys:

IABConsent.java
IABConsent.java
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, "");

Managing consent about geolocation for advertising purpose

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.

Presenting the notice

public class MainActivity extends AppCompatActivity {
@Override
protected 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);
}
}

Presenting the banner

public class MainActivity extends AppCompatActivity {
@Override
protected 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);
}
}

Presenting on user demand

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 notice
appConsent.presentGeolocationActivity(this, trigerredByUser);
// present a banner
appConsent.presentGeolocationBanner(aViewGroup, trigerredByUser);

Geolocation notice and banner callbacks

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() {
@Override
public void onResult(boolean b) {
Log.d(LOG_TAG, "Geoloc answer given: " + b);
}
@Override
public void onError(Throwable throwable) {
Log.e(LOG_TAG, "Geoloc error: " + throwable.getMessage());
}
});

Getting geolocation authorization status from the SDK

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() {
@Override
public void onSuccess() {
appConsent.presentNoticeActivity(false);
}
@Override
public 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.

Check for updates

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 {
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
String noticeUrl = "https://cdn.appconsent.io/<notice_path>";
AppConsent appConsent = new AppConsent(this, noticeUrl);
// check for updates
appConsent.checkForUpdate(new AppConsentUpdateCallback() {
@Override
public void onResult(boolean updated) {
if (updated) {
appConsent.presentNoticeActivity(false);
}
}
@Override
public void onError(Throwable t) {
// ...
}
});
}
}

Limiting the number of vendors from the IAB Global Vendor List

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
}
]
}

Extra purposes and extra vendors

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.

Untitled
"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.

Reading the status for extra purposes and extra vendors

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");

CMP Xchange Only - Huq SDK

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.

Configure your offline notice

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

notice.json
gvl.json
notice.json

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": {}
}
gvl.json
  • 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.

Customizing UI through the SDK theme

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

styles.xml
styles.xml
<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 builder
AppConsentTheme.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 object
AppConsentTheme theme = builder.build();
// Attach it when initalizing AppConsent
AppConsent 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:

MainActivity
MainActivity
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);
strings.xml
strings.xml
<resources>
<string name="text_with_link">Voici la <a href="https://www.sfbx.io/">Charte de confidentialité</a></string>
</resources>

IAB compliance

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

Updating SDK from 1.7 (or earlier) to 2.0.0 (or newer)

1. Create a new source with a bundle ID and a new notice

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.

2. Update the AppConsent SDK

3. Replace the notice url with the new one

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.

4. Update your assets files for the offline notice version

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.