Documentation

Table of Contents

iubenda SDK v3.5 Integration – Android

iubenda SDK is a comprehensive solution for managing user consent in mobile applications. Designed to handle GDPR compliance, user privacy preferences, and ad tracking transparency, this SDK provides a seamless integration for iOS and Android platforms.

Steps – High Level Description

  1. Integration and Configuration:
    • Integrate the SDK into your app.
    • Configure the SDK settings according to your needs.
  2. Creating an Instance and displaying the Consent Layer:
    • On app startup, create an instance of the CMPManager class. This instance will handle the consent process.
    • The SDK will automatically display the consent screen if needed.
  3. Processing user’s consent data:
    • Once consents are collected, info is stored and is available for querying through different properties and methods exposed by our SDK. You’ll have information about rejected or accepted consents, vendors and purposes.

1.1 Integration and Configuration

Adding dependency via Gradle

Add the following line to your build.gradle file:

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

1.2 Creating an instance and displaying consent layer

In your app’s onCreate method, follow these steps to set up the CMP SDK:

  1. Create a CMPManager instance using the getInstance method.
  2. Prepare two configuration objects:
    • UrlConfig: Includes your CMP settings like your iubenda embedding code and the language of the banner
    • ConsentLayerUIConfig: Sets the appearance of the WebView that will show the consent screen
  3. Pass the current Activity using setActivity.
    Set the delegate to handle CMP events.
  4. Set the delegate to handle CMP events.
  5. call the checkAndOpen() function:
    • This will automatically contact the server to determine whether the consent screen needs to be shown.
    • If required, the SDK will automatically present the consent layer inside a WebView, styled according to your configuration.
    • The SDK will then collect and store consent data in the device’s NSUserDefaults area, so the app can handle targeted advertising accordingly.

See a full configuration example below

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 = "<yoursiteID>",
            domain = "cdn.iubenda.com",
            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")
    }
}

Checking users’s consents

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

For further information about the other methods, please refer to our full API Documentation

Reopening the Consent Layer to check the users’ choices

In order to allow the user to verify or change their choices, you can simply call openConsentLayer()

cmpManager.forceOpen()

This method will display the consent layer via the same WebView instance created in the previous steps. 

Importing/Exporting consent information to other sources

In some cases an native app might contain webviews in order to display information, like advertising or content. In order to transmit the consent information from the SDK to the webview, you can retrieve the consent string using:

consentData = cmpManager.exportCMPInfo()

This will export the consent information and all further data that is needed by the CMP. You can then pass this information to the CMP that is in your webview by adding it to the URL that is called in the webview.
If, otherwise, you need to import the consent string using the SDK, you can use the example below:

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

Creating a custom layout

To create a customized view of the WKWebView, you can create a wrapper for the ComponentActivity that needs to be passed to the CMP SDK, so you have full control over the appearance and the lifecycle of it. For further information, please refer to the official documentation.

Logging

When using our iOS SDK, you may find the need to debug or analyze log information for various purposes. The logs generated by our SDK are tagged under “CMP”, allowing you to easily filter and view only the relevant logs.

Troubleshooting

Class Not Found or NoSuchMethodException:

ProGuard can sometimes obfuscate class names or remove methods that are dynamically referenced via reflection. To fix this, you need to specify the classes and methods that should be kept intact in the ProGuard configuration file using the -keep directive.

Example ProGuard configuration to keep a specific class and its methods:

# 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;
#}