[Android] 1. Integración del SDK de consentmanager

En este documento encontrarás información general sobre cómo integrar nuestro SDK en tu proyecto. Para obtener más detalles, consulta nuestra documentación de referencia de la API. Todos los fragmentos de código que aparecen a continuación se han extraído de nuestra aplicación de demostración

1. Instalación

consentmanager SDK es una solución integral para gestionar el consentimiento de los usuarios en aplicaciones móviles. Diseñado para gestionar el cumplimiento del RGPD, las preferencias de privacidad de los usuarios y la transparencia en el seguimiento publicitario, este SDK ofrece una integración perfecta para las plataformas iOS y Android. Además, ofrece plugins/puentes de envoltura para React Native, Flutter y Unity, lo que lo hace versátil en diversos entornos de desarrollo.

Pasos: descripción general

  1. Integración y configuración:

    • Integra el SDK en tu aplicación.
    • Configura los ajustes del SDK según tus necesidades.
  2. Creación de una instancia y visualización de la capa de consentimiento:

    • Al iniciar la aplicación, crea una instancia de la CMPManager clase. Esta instancia se encargará del proceso de consentimiento.
    • El SDK mostrará automáticamente la pantalla de consentimiento si es necesario.
  3. Tratamiento de los datos de consentimiento de los usuarios:

    • Una vez recopilados los consentimientos, la información se almacena y está disponible para su consulta a través de diferentes propiedades y métodos expuestos por nuestro SDK. Dispondrás de información sobre los consentimientos rechazados o aceptados, los proveedores y los fines.

1.1 Integración y configuración

Añadir la dependencia mediante Gradle

Añade la siguiente línea a tu archivo build.gradle:

dependencies {
    implementation "net.consentmanager.sdkv3:cmsdkv3:3.2.0"
}

A continuación, sincroniza tu proyecto. 

1.2 Creación de una instancia y visualización de la capa de consentimiento

Dentro de la función app-start (tu onCreate función), debes crear una instancia de la clase CMPManager. Tendrás que configurar dos objetos que se pasarán al método getInstance: UrlConfig, que gestiona tu configuración de CMP, como el Code-ID y el idioma predeterminado, y ConsentLayerUIConfig, que configurará el aspecto de la WebView que mostrará la capa de consentimiento. A continuación, pasarás la Activity utilizando el método setActivityy asignar el delegado, tal y como se muestra a continuación. En el ejemplo siguiente, puedes ver cómo se pasan ambos objetos. La checkAndOpen() función recuperará automáticamente los datos necesarios de nuestro servidor y determinará si es necesario mostrar la pantalla de consentimiento o no. Si es así, el SDK mostrará automáticamente la pantalla de consentimiento en este punto, a través de un WebView creada por nuestro SDK, que mostrará la capa de consentimiento con el texto y los botones según las configuraciones de tu CMP (seleccionadas mediante el Code-ID de tu CMP), recopilará los datos y almacenará la información de consentimiento en el área NSUserDefaults del dispositivo, para que la aplicación pueda mostrar los anuncios personalizados en consecuencia. 

Ten en cuenta que es fundamental declarar e inicializar el CMPManager SDK en el onCreate método; de lo contrario, es posible que la vista no esté lista para su uso y que el SDK falle. Respeta también el patrón singleton, de modo que solo tengas una instancia del SDK. Además, asegúrate de que estás utilizando los datos de configuración correctos. Los datos de configuración se encuentran en tu cuenta de ConsentManager en Menú > CMP > Obtener código para aplicaciones > ID de código

Además, ten en cuenta que las funcionalidades relacionadas con determinar si se necesita el consentimiento o no, así como la visualización de la capa de consentimiento, dependen de una conexión de red fiable. Si no hay conexión disponible o si el mecanismo de reintento no logra conectarse a nuestro servidor, el evento didReceiveError devolverá un error de tiempo de espera, por lo que el SDK será totalmente incapaz de determinar la necesidad de un consentimiento, ya que no podrá mostrar la capa de consentimiento. Asegúrate de que tu lógica tenga esto en cuenta.

Ejemplo:

import net.consentmanager.cm_sdk_android_v3.CMPManager
import net.consentmanager.cm_sdk_android_v3.CMPManagerDelegate
import net.consentmanager.cm_sdk_android_v3.ConsentLayerUIConfig
import net.consentmanager.cm_sdk_android_v3.UrlConfig

class MainActivity : ComponentActivity(), CMPManagerDelegate {
    private lateinit var cmpManager: CMPManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()

        val urlConfig = UrlConfig(
            id = "YOUR_CODE_ID_HERE",
            domain = "delivery.consentmanager.net",
            language = "EN",
            appName = "CMDemoAppKotlin"
        )

        val webViewConfig = ConsentLayerUIConfig(
            position = ConsentLayerUIConfig.Position.FULL_SCREEN,
            backgroundStyle = ConsentLayerUIConfig.BackgroundStyle.dimmed(Color.BLACK, 0.5f),
            cornerRadius = 10f,
            respectsSafeArea = true,
            isCancelable = false
        )

        cmpManager = CMPManager.getInstance(
            context = this,
            urlConfig = urlConfig,
            webViewConfig = webViewConfig,
            delegate = this
        )

        cmpManager.setActivity(this)

        checkAndOpen()
    }

    private fun checkAndOpenConsentLayer() {
        cmpManager.checkAndOpen { result ->
            result.onSuccess {
                showCMPDemoScreen()
            }.onFailure { error ->
                Log.e("DemoApp", "Check and open consent layer failed with error: $error")
            }
        }
    }

    private fun showCMPDemoScreen() {
        setContent {
            MaterialTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    CMPDemoScreen(cmpManager)
                }
            }
        }
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        Log.d("CMP DemoApp", "Configuration changed")
        super.onConfigurationChanged(newConfig)
        cmpManager.onApplicationResume()
    }

	override fun onPause() {
        Log.d("CMP DemoApp", "Activity paused")
        super.onPause()
        cmpManager.onApplicationPause()
    }

    override fun onDestroy() {
        Log.d("CMP DemoApp", "Activity destroyed")
        super.onDestroy()
        cmpManager.onActivityDestroyed()
    }

    override fun didReceiveConsent(consent: String, jsonObject: Map<String, Any>) {
        Log.d("CMP DemoApp", "Consent Layer successfully received consent message.")
        runOnUiThread {
            showCMPDemoScreen()
        }
    }

    override fun didShowConsentLayer() {
        Log.d("CMP DemoApp", "Consent Layer open message received.")
    }

    override fun didCloseConsentLayer() {
        Log.d("CMP DemoApp", "Consent Layer close message received.")
        runOnUiThread {
            showCMPDemoScreen()
        }
    }

    override fun didReceiveError(error: String) {
        Log.e("CMP DemoApp", "SDK error: $error")
    }
}

1.3 Tratamiento de los datos de consentimiento de los usuarios

Comprobación de los consentimientos de los usuarios

Our SDK offer a unified method to check and retrieve consent information, getUserStatus() :
val status = cmpManager.getUserStatus()
Log.d("CMPDemo", "User Status: ${status.hasUserChoice}")
Log.d("CMPDemo", "TCF: ${status.tcf}")
Log.d("CMPDemo", "Additional Consent: ${status.addtlConsent}")
Log.d("CMPDemo", "Regulation: ${status.regulation}")

Log.d("CMPDemo", "---- Vendors Status ----")
status.vendors.forEach { (vendorId, choice) ->
    Log.d("CMPDemo", "Vendor $vendorId: $choice")
}

Log.d("CMPDemo", "---- Purposes Status ----")
status.purposes.forEach { (purposeId, choice) ->
    Log.d("CMPDemo", "Purpose $purposeId: $choice")
}

Para obtener más información sobre los demás métodos, consulta nuestra documentación completa de la API

Reabrir la ventana de consentimiento para comprobar las elecciones de los usuarios

Para que el usuario pueda verificar o cambiar sus opciones, basta con llamar a openConsentLayer()

cmpManager.forceOpen()

Este método mostrará la capa de consentimiento a través de la misma instancia de WebView creada en los pasos anteriores. 

Importación/exportación de información sobre el consentimiento a otras fuentes

En algunos casos, una aplicación nativa puede contener vistas web para mostrar información, como publicidad o contenido. Para transmitir la información de consentimiento desde el SDK a la vista web, puedes recuperar la cadena de consentimiento utilizando:

consentData = cmpManager.exportCMPInfo()

Esto exportará la información de consentimiento y todos los datos adicionales que necesita el CMP. A continuación, puedes pasar esta información al CMP que se encuentra en tu vista web añadiéndola a la URL que se llama en la vista web.

Si, por el contrario, necesitas importar la cadena de consentimiento utilizando el SDK, puedes usar el ejemplo siguiente:

val consentStringToImport = "Q1FERkg3QVFERkg3QUFmR01CSVRCQkVnQUFBQUFBQUFBQWlnQUFBQUFBQUEjXzUxXzUyXzUzXzU0XzU1XzU2XyNfczI3ODlfczI3OTBfczI3OTFfczI2OTdfczk3MV9VXyMxLS0tIw"
cmpManager.importCMPInfo(consentStringToImport)

Creación de un diseño personalizado

Para crear una vista personalizada de WKWebView, puedes crear un contenedor para ComponentActivity que debe pasarse al SDK de CMP, de modo que tengas control total sobre su apariencia y su ciclo de vida. Para obtener más información, consulta la documentación oficial.

Inicio de sesión

Al utilizar nuestro SDK para iOS, es posible que necesites depurar o analizar la información de los registros con diversos fines. Los registros generados por nuestro SDK están etiquetados como «CMP», lo que te permite filtrarlos fácilmente y ver solo los registros relevantes. Para obtener más información, consulta esta sección de nuestra documentación.

Solución de problemas

Clase no encontrada o NoSuchMethodException:

ProGuard a veces puede ofuscar nombres de clases o eliminar métodos a los que se hace referencia dinámicamente mediante reflexión. Para solucionar esto, debes especificar las clases y los métodos que deben mantenerse intactos en el archivo de configuración de ProGuard utilizando la -keep directiva.

Ejemplo de configuración de ProGuard para conservar una clase específica y sus métodos:

# Kotlin serialization looks up the generated serializer classes through a function on companion
# objects. The companions are looked up reflectively so we need to explicitly keep these functions.
-keepclasseswithmembers class **.*$Companion {
    kotlinx.serialization.KSerializer serializer(...);
}
# If a companion has the serializer function, keep the companion field on the original type so that
# the reflective lookup succeeds.
-if class **.*$Companion {
  kotlinx.serialization.KSerializer serializer(...);
}
-keepclassmembers class <1>.<2> {
  <1>.<2>$Companion Companion;
}

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}

-keepattributes JavascriptInterface

-keepclassmembers class net.consentmanager.sdk.common.callbacks.* {
   public *;
}

-keepclassmembers class net.consentmanager.sdk.consentlayer.ui.consentLayer.CmpWebView {
   public *;
}

-keepclassmembers class net.consentmanager.sdk.consentlayer.ui.CmpLayerAppInterface {
   public *;
}
-keep class net.consentmanager.sdk.CMPConsentTool {
                                                      *;
                                                  }

-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}

-keepattributes JavascriptInterface

# Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`.
# If you have any, uncomment and replace classes with those containing named companion objects.
#-keepattributes InnerClasses # Needed for `getDeclaredClasses`.
#-if @kotlinx.serialization.Serializable class
#com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.
#com.example.myapplication.HasNamedCompanion2
#{
#    static **$* *;
#}
#-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept.
#    static <1>$$serializer INSTANCE;
#}

 

We do our best to keep this purely informative documentation up to date. However, if you notice that any of these guides need a little touch-up, let us know!