Cómo integrar el SDK de UniConsent CMP para Android con aplicaciones móviles

UniConsent CMP es un paquete para gestionar el consentimiento GDPR IAB TCF 2.3 en aplicaciones Android. Puede encontrar una aplicación de demostración integrada con UniConsent CMP en el directorio "demo".

Requisitos previos

  • Plan de UniConsent CMP con soporte para aplicaciones móviles
  • Nivel de API de Android 21 o superior
  • Paquete del SDK de UniConsent CMP (solicitar al soporte)

Primeros pasos

Agregue UniConsentSDK-release.aar en el directorio libs/ de su proyecto y actualice su 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'

Personalizar la interfaz de consentimiento

Antes de integrar el SDK, personalice la apariencia del banner de consentimiento en el Panel de UniConsent para que coincida con su marca y optimice las tasas de consentimiento.

Paso 1: Estilo de marca en el panel

Vaya a Projects → Seleccione su Proyecto → Settings → Step 5: UI & Style Settings para configurar:

  • Main Button Colour — Establezca el color del botón de acción principal para que coincida con su marca
  • Main Button Text Colour — Ajuste el color del texto del botón principal para mejorar la legibilidad
  • Background Colour — Establezca el color de fondo del banner para que se integre con su aplicación
  • Text Colour — Asegúrese de que el texto del cuerpo tenga el contraste adecuado

Paso 2: Estilo avanzado con CSS personalizado (Opcional)

Para un control más preciso, agregue CSS personalizado en el campo CSS Content en el Paso 5. Esto se recomienda para que el banner se sienta nativo en su aplicación y logre la mejor tasa de consentimiento:

/* 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;
}

Consejo: Una interfaz de consentimiento bien personalizada que se sienta nativa en su aplicación generalmente logra tasas de consentimiento más altas. Los usuarios tienen más probabilidades de interactuar positivamente con un banner que coincide con la apariencia que esperan.

Uso

Para usar UniConsent CMP en su aplicación, siga estos pasos:

Inicialice el CMP con un App ID proporcionado por su gestor de cuenta:

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

Mostrar la interfaz del 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);

También puede lanzar con una etapa y modo de visualización específicos:

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

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

Verificar automáticamente si el consentimiento ha expirado cuando se actualiza la vendorList:

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

Obtener el tcString si es necesario:

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

Leer el estado del consentimiento:

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

Restablecer el estado del consentimiento si es necesario:

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

Sincronizar consentimiento con WebView

Si su aplicación abre un WebView que carga una página web con la etiqueta de UniConsent CMP, puede pasar el estado de consentimiento nativo para que la etiqueta del CMP reconozca el consentimiento existente y no muestre el banner nuevamente.

Inyecte el consentimiento al inicio de la página, antes de que se ejecute la etiqueta del 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");

Ejemplo usando 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);
    }
}

Ejemplo usando 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)
    }
}

Permisos

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

Configurar el estado de consentimiento predeterminado KV:

<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" />

Controlar la analítica basada en las opciones de consentimiento:


// <= 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 logics such as send analytics events
}

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

    // other logics 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);
}

Encuentre más información en Set up consent mode for apps

Modos de visualización

El SDK soporta tres modos de visualización para la interfaz de consentimiento, coincidiendo con la API del SDK de Flutter:

ModoEnumDescripción
Pantalla completaCMPDisplayMode.FULL_SCREENAbre el CMP en una nueva actividad a pantalla completa (predeterminado)
Hoja inferiorCMPDisplayMode.BOTTOM_SHEETSe desliza desde la parte inferior como una hoja modal (85% de altura)
DiálogoCMPDisplayMode.DIALOGSe muestra como un diálogo centrado (90% de ancho, 75% de altura)

Nota: Los modos de hoja inferior y diálogo requieren que su Activity extienda AppCompatActivity o FragmentActivity.

Notas

  1. Los usuarios deben tener la posibilidad de acceder a un botón o enlace de "Configuración de privacidad" en la sección de ajustes de su aplicación para abrir la interfaz del CMP.
  2. Puede utilizar la función shouldRequestConsent() para verificar si debe solicitar un nuevo consentimiento según el estado. Muestre la interfaz del CMP según sea necesario cuando un usuario abra la aplicación.
  3. A partir de la versión 25.6.1 del SDK, ya no necesita enviar manualmente las opciones de consentimiento para FirebaseAnalytics o ciertos SDK de AAP compatibles, ya que se gestionan automáticamente por el SDK. Para más información, consulte ¿Qué es Google AAP y Google MMP para aplicaciones móviles?.