Leading Consent Management Platform

Compliant with GDPR, CCPA, COPPA, LGPD, PECR, PDPA, PIPEDA, and more.

Come integrare l'SDK CMP UniConsent per Android nelle app mobili

UniConsent CMP è un pacchetto per la gestione del consenso GDPR IAB TCF 2.4 nelle app Android. Nella directory "demo" trovi un'app dimostrativa integrata con UniConsent CMP.

Prerequisiti

  • Piano UniConsent CMP con supporto per le app mobili
  • Livello API Android 21 o superiore
  • Pacchetto SDK UniConsent CMP (da richiedere al supporto)

Per iniziare

Aggiungi UniConsentSDK-release.aar alla directory libs/ del tuo progetto e aggiorna il file build.gradle:

implementation files('libs/UniConsentSDK-release.aar')
implementation 'androidx.appcompat:appcompat:1.7.1'
implementation 'com.google.android.material:material:1.13.0'
implementation 'com.iabtcf:iabtcf-core:2.0.10'
implementation 'com.iabtcf:iabtcf-decoder:2.0.10'

Personalizzare l'interfaccia del consenso

Prima di integrare l'SDK, personalizza l'aspetto del banner del consenso nella Dashboard UniConsent per adattarlo al tuo brand e ottimizzare i tassi di consenso.

Passaggio 1: stile del brand nella Dashboard

Vai a Projects → Select your Project → Settings → Step 5: UI & Style Settings per configurare:

  • Main Button Colour: imposta il colore del pulsante di azione principale in linea con il tuo brand
  • Main Button Text Colour: regola il colore del testo del pulsante principale per garantirne la leggibilità
  • Background Colour: imposta il colore di sfondo del banner in armonia con la tua app
  • Text Colour: assicurati che il testo del corpo abbia un contrasto adeguato

Passaggio 2: stile avanzato con CSS personalizzato (facoltativo)

Per un controllo più preciso, aggiungi CSS personalizzato nel campo CSS Content del passaggio 5. È consigliato per far sembrare il banner parte integrante della tua app e ottenere il miglior tasso di consenso:

/* Example: Style the accept button to match your brand */
.unic-btn-accept {
  background-color: #4CAF50;
  border-radius: 8px;
  font-weight: 600;
}

/* Example: Adjust banner font */
.unic-banner {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* Example: Make the reject button less prominent */
.unic-btn-reject {
  background-color: transparent;
  border: 1px solid #ccc;
  color: #666;
}

Suggerimento: un'interfaccia del consenso coerente con il brand e integrata nella tua app ottiene in genere tassi di consenso più elevati. Gli utenti tendono a interagire in modo più positivo con un banner che rispecchia l'aspetto e lo stile che si aspettano.

Utilizzo

Per usare UniConsent CMP nella tua app, segui questi passaggi:

Inizializza la CMP con un App ID fornito dal tuo account manager:

UniConsent UniConsentCMP = UniConsent.getInstance();
UniConsentCMP.setAppId("YOUR_APP_ID");

Mostra l'interfaccia della CMP:

// Display CMP as full-screen page (default)
UniConsent.getInstance().launchCMP();

// Display CMP as a modal bottom sheet
UniConsent.getInstance().launchCMP(CMPDisplayMode.BOTTOM_SHEET);

// Display CMP as a center dialog
UniConsent.getInstance().launchCMP(CMPDisplayMode.DIALOG);

Puoi anche avviarla con una fase e una modalità di visualizzazione specifiche:

// Launch at a specific stage with a display mode
UniConsent.getInstance().launchCMP(Stage.GDPRFirstScreen, CMPDisplayMode.BOTTOM_SHEET);

// Bottom sheet at 70% of the screen height
UniConsent.getInstance().launchCMP(Stage.GDPRFirstScreen, CMPDisplayMode.BOTTOM_SHEET, 0.7);

// Center dialog at 80% width and 60% height
UniConsent.getInstance().launchCMP(Stage.GDPRFirstScreen, CMPDisplayMode.DIALOG, 0.8, 0.6);

// Or set a default display mode for all launches
UniConsent.getInstance().setDisplayMode(CMPDisplayMode.BOTTOM_SHEET);
UniConsent.getInstance().launchCMP();

Dimensioni personalizzate (facoltativo)

Disponibile dalla versione 26.8.0 dell'SDK.

Entrambi i rapporti sono facoltativi: ogni modalità di visualizzazione funziona anche senza. Passa un rapporto (una frazione dello schermo, maggiore di 0 e al massimo 1) solo per sovrascrivere le dimensioni predefinite; i valori non validi generano IllegalArgumentException:

ParametroSi applica aValore predefinito se omesso
heightRatioBOTTOM_SHEET, DIALOGSheet: 90% dello schermo. Dialog: 70%
widthRatioSolo DIALOG90% della larghezza dello schermo, fino a 500dp

I rapporti che non si applicano alla modalità di visualizzazione scelta vengono ignorati (FULL_SCREEN li ignora entrambi).

Verifica automaticamente se il consenso è scaduto quando la vendorList viene aggiornata:

// Check if consent should be requested (e.g. first visit, or vendor list updated)
if (UniConsentCMP.shouldRequestConsent()) {
    UniConsentCMP.launchCMP();
}

Ottieni la tcString, se necessario:

// Get tcString
UniConsent.getInstance().getTCString();

Leggi lo stato del consenso:

// Read consent status
UniConsent.getInstance().hasIABPurposeConsent(1);
UniConsent.getInstance().hasIABVendorConsent(1);

Reimposta lo stato del consenso, se necessario:

// Reset consent status
UniConsent.getInstance().clearData();

Primo livello personalizzato (Accetta tutto / Rifiuta tutto)

Disponibile dalla versione 26.7.0 dell'SDK. Se crei una tua interfaccia di primo livello per il consenso invece di mostrare la webview della CMP, puoi salvare il consenso direttamente:

// Grant consent for all purposes, special features and vendors
boolean saved = UniConsent.getInstance().agreeAll();

// Reject all purposes, special features and vendors
boolean saved = UniConsent.getInstance().rejectAll();

Entrambe le API salvano gli stessi valori di consenso del flusso dell'interfaccia della CMP (chiavi IAB TCF, additional consent e segnali di Consent Mode) e inviano lo stesso evento di chiusura ai sottoscrittori.

Nota: chiama queste API solo dopo il completamento di init() (ad esempio dopo l'evento READY). Richiedono la vendor list e la configurazione del progetto, che vengono recuperate durante l'inizializzazione, e restituiscono false se non è stato possibile salvare il consenso.

Importante: il tuo primo livello personalizzato deve comunque rispettare i requisiti IAB TCF (indicare le finalità e i fornitori e offrire le opzioni di accettazione e rifiuto con uguale evidenza). Gli utenti devono comunque poter aprire l'interfaccia completa della CMP (launchCMP()) per effettuare scelte granulari.

Sincronizzare il consenso con la WebView

Se la tua app apre una WebView che carica una pagina web con il tag CMP di UniConsent, puoi passare lo stato del consenso nativo in modo che il tag CMP riconosca il consenso esistente e non mostri di nuovo il banner.

Inietta il consenso all'avvio della pagina, prima che venga eseguito il tag CMP:

WebView webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageStarted(WebView view, String url, android.graphics.Bitmap favicon) {
        UniConsent.getInstance().syncConsent(view);
    }
});

webView.loadUrl("https://example.com");

Esempio con AppCompatActivity

import com.uniconsent.sdk.CMPDisplayMode;
import com.uniconsent.sdk.Event;
import com.uniconsent.sdk.EventHandler;
import com.uniconsent.sdk.Stage;
import com.uniconsent.sdk.UniConsent;

public class MainActivity extends AppCompatActivity implements EventHandler {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        UniConsent UniConsentCMP = UniConsent.getInstance();
        UniConsentCMP.setAppId("YOUR_APP_ID");
        UniConsentCMP.init(this);
        // register callback events
        UniConsentCMP.subscribe(this);
        // check if consent should be requested
        if (UniConsentCMP.shouldRequestConsent()) {
            UniConsentCMP.launchCMP();
        }
    }

    public void openUniConsentUI(View view) {
        // Full screen
        UniConsent.getInstance().launchCMP(Stage.GDPRFirstScreen);
    }

    public void openAsBottomSheet(View view) {
        // Bottom sheet
        UniConsent.getInstance().launchCMP(Stage.GDPRFirstScreen, CMPDisplayMode.BOTTOM_SHEET);
    }

    public void openAsDialog(View view) {
        // Center dialog
        UniConsent.getInstance().launchCMP(Stage.GDPRFirstScreen, CMPDisplayMode.DIALOG);
    }

    @Override
    public void handle(Event event) {
        UniConsent.getInstance().hasIABVendorConsent(1);
    }
}

Esempio con ComponentActivity

package com.example.myapplication

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.example.myapplication.ui.theme.MyApplicationTheme
import com.uniconsent.sdk.CMPDisplayMode
import com.uniconsent.sdk.Event
import com.uniconsent.sdk.EventHandler
import com.uniconsent.sdk.Stage
import com.uniconsent.sdk.UniConsent

class MainActivity : ComponentActivity(), EventHandler {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val cmp = UniConsent.getInstance()
        cmp.appId = "YOUR_APP_ID"
        cmp.init(this)
        cmp.subscribe(this)

        if (cmp.shouldRequestConsent()) {
             cmp.launchCMP();
        }
        setContent {
            MyApplicationTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(16.dp),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        Button(onClick = {
                            UniConsent.getInstance().launchCMP(Stage.GDPRFirstScreen)
                        }) {
                            Text("Privacy Settings")
                        }
                        Spacer(modifier = Modifier.height(16.dp))
                        Button(onClick = {
                            UniConsent.getInstance().launchCMP(
                                Stage.GDPRFirstScreen, CMPDisplayMode.BOTTOM_SHEET
                            )
                        }) {
                            Text("Privacy Settings (Bottom Sheet)")
                        }
                        Spacer(modifier = Modifier.height(16.dp))
                        Button(onClick = {
                            UniConsent.getInstance().launchCMP(
                                Stage.GDPRFirstScreen, CMPDisplayMode.DIALOG
                            )
                        }) {
                            Text("Privacy Settings (Dialog)")
                        }
                    }
                }
            }
        }
    }

    override fun handle(event: Event?) {
        Log.d("CMP_EVENT", event.toString())
        UniConsent.getInstance().hasIABVendorConsent(1)
    }
}

Autorizzazioni

<uses-permission android:name="android.permission.INTERNET" />

Configura i valori chiave (KV) predefiniti dello stato del consenso:

<meta-data android:name="firebase_analytics_collection_enabled" android:value="false" />

<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_storage" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="false" />

Controlla gli analytics in base ai flag del consenso:


// <= 25.6.1
override fun handle(event: Event?) {
    Log.d("CMP_EVENT", event.toString())
    if(UniConsent.getInstance().hasIABPurposeConsent(1)) {
        // Set consent types.
        Map<FirebaseAnalytics.ConsentType, FirebaseAnalytics.ConsentStatus> consentMap = new EnumMap<>(FirebaseAnalytics.ConsentType.class);
        consentMap.put(FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE, FirebaseAnalytics.ConsentStatus.GRANTED);
        consentMap.put(FirebaseAnalytics.ConsentType.AD_STORAGE, FirebaseAnalytics.ConsentStatus.GRANTED);
        consentMap.put(FirebaseAnalytics.ConsentType.AD_USER_DATA, FirebaseAnalytics.ConsentStatus.GRANTED);
        consentMap.put(FirebaseAnalytics.ConsentType.AD_PERSONALIZATION, FirebaseAnalytics.ConsentStatus.GRANTED);

        mFirebaseAnalytics.setConsent(consentMap);
        mFirebaseAnalytics.setAnalyticsCollectionEnabled(true);
    } else {
        // Set consent types.
        Map<FirebaseAnalytics.ConsentType, FirebaseAnalytics.ConsentStatus> consentMap = new EnumMap<>(FirebaseAnalytics.ConsentType.class);
        consentMap.put(FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE, FirebaseAnalytics.ConsentStatus.DENIED);
        consentMap.put(FirebaseAnalytics.ConsentType.AD_STORAGE, FirebaseAnalytics.ConsentStatus.DENIED);
        consentMap.put(FirebaseAnalytics.ConsentType.AD_USER_DATA, FirebaseAnalytics.ConsentStatus.DENIED);
        consentMap.put(FirebaseAnalytics.ConsentType.AD_PERSONALIZATION, FirebaseAnalytics.ConsentStatus.DENIED);

        mFirebaseAnalytics.setConsent(consentMap);
        mFirebaseAnalytics.setAnalyticsCollectionEnabled(false);
    }

    // other logic such as send analytics events
}

// > 25.6.1
override fun handle(event: Event?) {
    Log.d("CMP_EVENT", event.toString())

    // other logic such as send analytics events

    // Example: send Firebase event or other analytics metrics
    Bundle bundle = new Bundle();
    bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "id");
    bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "name");
    bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "image");
    mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, bundle);
}

Trova maggiori informazioni in Set up consent mode for apps

Modalità di visualizzazione

L'SDK supporta tre modalità di visualizzazione per l'interfaccia del consenso, in linea con l'API dell'SDK Flutter:

ModalitàEnumDescrizione
Schermo interoCMPDisplayMode.FULL_SCREENApre la CMP in una nuova activity a schermo intero (predefinita)
Bottom sheetCMPDisplayMode.BOTTOM_SHEETScorre dal basso come foglio modale (85% dell'altezza)
DialogCMPDisplayMode.DIALOGViene mostrata come finestra di dialogo centrata (90% della larghezza, 75% dell'altezza)

Nota: le modalità bottom sheet e dialog richiedono che la tua Activity estenda AppCompatActivity o FragmentActivity.

Note

  1. Gli utenti devono poter accedere a un pulsante o link "Impostazioni privacy" nella sezione delle impostazioni della tua applicazione per aprire l'interfaccia della CMP.
  2. Puoi usare la funzione shouldRequestConsent() per verificare, in base allo stato, se occorre richiedere un nuovo consenso. Mostra l'interfaccia della CMP quando necessario all'apertura dell'applicazione da parte dell'utente.
  3. A partire dalla versione 25.6.1 dell'SDK non è più necessario inviare manualmente le opzioni di consenso per FirebaseAnalytics o per alcuni SDK AAP supportati: vengono gestite automaticamente dall'SDK. Per maggiori informazioni, consulta Che cosa sono Google AAP e Google MMP per le app mobili?.

Changelog

26.9.0

  • Supporto per IAB TCF 2.4