PubConsent
Android Integration
28min
the pubconsent sdk is the integration of our pubconsent cmp into android applications the strength of our integration is that it does not require many updates since any changes made within the configurator will be automatically reflected within the app (excluding some specific configurations that need to be done programmatically) minimum sdk version 21 every time significant changes are introduced, you will be contacted via email at the technical address you have configured in our dashboard, allowing you to update the sdk version to the latest one we have published for more api or more info of how it works needed don't hesitate to contact our customer support every bug or problems during the integration will be a great feedback for us, please don't hesitate to contact us, your satisfaction is our great reward setup to use the pubconsent sdk in your android project, add the following dependency to your build gradle our cmp sdk is available on maven central here implementation 'ai pubtech pubconsent\ pubconsent sdk 3 0 0' permissions this sdk requires the following permissions, please ensure to add them to your androidmanifest xml \<uses permission android\ name="android permission access network state" /> \<uses permission android\ name="android permission internet" /> how it works once the sdk is integrated into an app, it will automatically prompt and display the user interface if necessary the sdk will retrieve information from our server to prepare and provide your cmp, which you have configured through our dashboard when the app wants to process personal data, it should "ask" the sdk if consent has been given for the specific purpose and provider kotlin example import ai pubtech pubconsent cmp import ai pubtech pubconsent cmpcallbacks import ai pubtech pubconsent cmpconfig import ai pubtech pubconsent dto googleconsentmodestatus import ai pubtech pubconsent dto googleconsentmodetype import ai pubtech pubconsent utility cmplogger import androidx appcompat app appcompatactivity import android os bundle import android widget button class mainactivity appcompatactivity() { override fun oncreate(savedinstancestate bundle?) { super oncreate(savedinstancestate) setcontentview(r layout activity main) // configure the fragmentcontainerid if you use the cmp inside a activityfragment >> cmpuiconfig uitype = cmpuitype fragment cmpuiconfig fragmentcontainerid = android r id content // choose how to see the cmp cmpuiconfig configurecenterscreen(this) val cmp = cmp createinstance(this) 	 // create cmpcallbacks (this is optional) val cmpcallbacks = cmpcallbacks( { consentapiinterface > if (consentapiinterface getcmptype() == cmptype tcf v2 gdpr) { consentapiinterface as tcfgdprconsentapi cmplogger d("from my app consent ready and it's a tcf v2 gdpr") cmplogger d("vendor expo is enabled ${consentapiinterface isvendorconsentenabled(1)}") cmplogger d("features ${consentapiinterface isfeaturecookiesenabled()}") cmplogger d("user experience ${consentapiinterface isuserexperiencecookiesenabled()}") cmplogger d("measurement ${consentapiinterface ismeasurementcookiesenabled()}") val firebaseconsentmap = consentapiinterface getgoogleconsentmode()? entries? associate { entry > val firebaseconsenttype = when (entry key) { googleconsentmodetype analytics storage > "firebaseanalytics consenttype analytics storage" googleconsentmodetype ad storage > "firebaseanalytics consenttype ad storage" googleconsentmodetype ad user data > "firebaseanalytics consenttype ad user data" googleconsentmodetype ad personalization > "firebaseanalytics consenttype ad personalization" googleconsentmodetype functionality storage > "opzionale" googleconsentmodetype personalization storage > "opzionale" googleconsentmodetype security storage > "opzionale" } val firebaseconsentstatus = when (entry value) { googleconsentmodestatus granted > "firebaseanalytics consentstatus granted" googleconsentmodestatus denied > "firebaseanalytics consentstatus denied" googleconsentmodestatus unknown > "non mappato nel caso in cui non siano disponibili i tipi opzionali " } firebaseconsenttype to firebaseconsentstatus } cmplogger d("firebase mapping $firebaseconsentmap") } if (consentapiinterface getcmptype() == cmptype google consent mode) { consentapiinterface as gcmconsentapi cmplogger d("la cmp è basata sul google consent mode ed è il consenso è pronto!") val firebaseconsentmap = consentapiinterface getgoogleconsentmode()? entries? associate { entry > val firebaseconsenttype = when (entry key) { googleconsentmodetype analytics storage > "firebaseanalytics consenttype analytics storage" googleconsentmodetype ad storage > "firebaseanalytics consenttype ad storage" googleconsentmodetype ad user data > "firebaseanalytics consenttype ad user data" googleconsentmodetype ad personalization > "firebaseanalytics consenttype ad personalization" googleconsentmodetype functionality storage > "opzionale da abilitare nel configuratore" googleconsentmodetype personalization storage > "opzionale da abilitare nel configuratore" googleconsentmodetype security storage > "opzionale da abilitare nel configuratore" } val firebaseconsentstatus = when (entry value) { googleconsentmodestatus granted > "firebaseanalytics consentstatus granted" googleconsentmodestatus denied > "firebaseanalytics consentstatus denied" googleconsentmodestatus unknown > "non mappato nel caso in cui non siano disponibili i tipi opzionali " } firebaseconsenttype to firebaseconsentstatus } cmplogger d("firebase mapping $firebaseconsentmap") } }, { cmplogger d("from cmp sdk the ui was closed") }, { cmplogger d("from cmp sdk the ui showed") }, { cmplogger d("from cmp sdk error $it") }, { consentmap > //warning this callback will be deleted in v3 0 0 use the consentapiinterface as explained before val firebaseconsentmap = consentmap entries associate { entry > val firebaseconsenttype = when (entry key) { googleconsentmodetype analytics storage > "firebaseanalytics consenttype analytics storage" googleconsentmodetype ad storage > "firebaseanalytics consenttype ad storage" googleconsentmodetype ad user data > "firebaseanalytics consenttype ad user data" googleconsentmodetype ad personalization > "firebaseanalytics consenttype ad personalization" } val firebaseconsentstatus = when (entry value) { googleconsentmodestatus granted > "firebaseanalytics consentstatus granted" googleconsentmodestatus denied > "firebaseanalytics consentstatus denied" } firebaseconsenttype to firebaseconsentstatus } cmplogger d("firebase mapping $firebaseconsentmap") } ) 	 // create cmpconfig val cmpconfig = cmpconfig("your cmp id", appname = "your app name", true, cmpcallbacks) 	 // run the cmp by providing the cmpconfig cmp run(this, cmpconfig) val button = findviewbyid\<button>(r id button) // set a button to open the cmp so to re ask consent to the user button setonclicklistener { cmp shownotice(this) } } } java example import ai pubtech pubconsent cmp; import ai pubtech pubconsent cmpcallbacks; import ai pubtech pubconsent cmpconfig; import ai pubtech pubconsent dto googleconsentmodestatus; import ai pubtech pubconsent dto googleconsentmodetype; import ai pubtech pubconsent utility cmplogger; import androidx appcompat app appcompatactivity; import android os bundle; import android widget button; public class mainactivity extends appcompatactivity { @override protected void oncreate(bundle savedinstancestate) { super oncreate(savedinstancestate); setcontentview(r layout activity main); // configure the fragmentcontainerid if you use the cmp inside an activityfragment >> cmpuiconfig uitype = cmpuitype fragment cmpuiconfig instance fragmentcontainerid = android r id content; // choose how to see the cmp cmpuiconfig instance configurecenterscreen(this); cmp cmp = cmp createinstance(this); // create cmpcallbacks (this is optional) cmpcallbacks cmpcallbacks = new cmpcallbacks( consentapiinterface > { if (consentapiinterface getcmptype() == cmptype tcf v2 gdpr) { tcfgdprconsentapi gdprconsentapi = (tcfgdprconsentapi) consentapiinterface; cmplogger d("based on tcf v2 for gdpr ed consent is ready"); cmplogger d("the vendor with id 1 is enabled " + cmp isvendorconsentenabled(1)); cmplogger d("features " + cmp isfeaturecookiesenabled()); cmplogger d("user experience " + cmp isuserexperiencecookiesenabled()); cmplogger d("measurement " + cmp ismeasurementcookiesenabled()); map\<string, string> firebaseconsentmap = gdprconsentapi getgoogleconsentmode() entryset() stream() collect(collectors tomap( entry > { switch (entry getkey()) { case analytics storage return "firebaseanalytics consenttype analytics storage"; case ad storage return "firebaseanalytics consenttype ad storage"; case ad user data return "firebaseanalytics consenttype ad user data"; case ad personalization return "firebaseanalytics consenttype ad personalization"; case functionality storage return "opzionale"; case personalization storage return "opzionale"; case security storage return "opzionale"; default return ""; } }, entry > { switch (entry getvalue()) { case granted return "firebaseanalytics consentstatus granted"; case denied return "firebaseanalytics consentstatus denied"; case unknown return "not mapped in case optional types aren't used "; default return ""; } } )); cmplogger d("firebase mapping " + firebaseconsentmap); } else if (consentapiinterface getcmptype() == cmptype google consent mode) { gcmconsentapi gcmconsentapi = (gcmconsentapi) consentapiinterface; cmplogger d("consent ready with cmp based on google consent mode only!"); map\<string, string> firebaseconsentmap = gcmconsentapi getgoogleconsentmode() entryset() stream() collect(collectors tomap( entry > { switch (entry getkey()) { case analytics storage return "firebaseanalytics consenttype analytics storage"; case ad storage return "firebaseanalytics consenttype ad storage"; case ad user data return "firebaseanalytics consenttype ad user data"; case ad personalization return "firebaseanalytics consenttype ad personalization"; case functionality storage return "can be enabled within the configurator "; case personalization storage return "can be enabled within the configurator "; case security storage return "can be enabled within the configurator "; default return ""; } }, entry > { switch (entry getvalue()) { case granted return "firebaseanalytics consentstatus granted"; case denied return "firebaseanalytics consentstatus denied"; case unknown return "optional types can be unknown if they aren't enabled within the configurator "; default return ""; } } )); cmplogger instance d("firebase mapping " + firebaseconsentmap); } }, () > { cmplogger instance d("from cmp sdk the ui was closed"); }, () > { cmplogger instance d("from cmp sdk the ui showed"); }, it > { cmplogger instance d("from cmp sdk error " + it); }, consentmap > { //warning this callback will be deleted in v3 0 0 use the consentapiinterface as explained before map\<string, string> firebaseconsentmap = new hashmap<>(); for (map entry\<googleconsentmodetype, googleconsentmodestatus> entry consentmap entryset()) { string firebaseconsenttype = null; switch (entry getkey()) { case analytics storage firebaseconsenttype = "firebaseanalytics consenttype analytics storage"; break; case ad storage firebaseconsenttype = "firebaseanalytics consenttype ad storage"; break; case ad user data firebaseconsenttype = "firebaseanalytics consenttype ad user data"; break; case ad personalization firebaseconsenttype = "firebaseanalytics consenttype ad personalization"; break; } string firebaseconsentstatus = null; switch (entry getvalue()) { case granted firebaseconsentstatus = "firebaseanalytics consentstatus granted"; break; case denied firebaseconsentstatus = "firebaseanalytics consentstatus denied"; break; } if (firebaseconsenttype != null && firebaseconsentstatus != null) { firebaseconsentmap put(firebaseconsenttype, firebaseconsentstatus); } } cmplogger instance d("firebase mapping " + firebaseconsentmap); } ); // create cmpconfig cmpconfig cmpconfig = new cmpconfig("your cmp id", "your app name", true, cmpcallbacks); // run the cmp by providing the cmpconfig cmp run(this, cmpconfig); button button = findviewbyid(r id button); // set a button to open the cmp so to re ask consent to the user button setonclicklistener(view > cmp shownotice(this)); } } consent sharing with webview if you need to reuse the consent collected through our sdk in a webview pointing to your website, you can refer to the documentation consent sharing with webview docid\ zoopmmq mqsabxypt4cro layout configuration for configuring the layout you can use the cmpuiconfig class with different styling options this class offers also some preset layouts like configurehalfscreenbottom configurehalfscreentop configurecenterscreen configuresmallcenterscreen configurelargetopscreen configurelargebottomscreen the default ui type will be the one that use the popup window, you can change the ui type by setting the uiconfig parameter cmpuiconfig uitype = cmpuitype dialog cmpuiconfig uitype = cmpuitype popup cmpuiconfig uitype = cmpuitype fragment cmpuiconfig uitype = cmpuitype activity two important parameter will determine the popup and dialog behaviour popup behaviour parameter isfocusable = true isfocusable = false isoutsidetouchable = true dismisses on outside touch can gain focus for input events dismisses on outside touch does not gain focus or intercept keyboard input isoutsidetouchable = false does not dismiss on outside touch can gain focus and intercept input events does not dismiss on outside touch does not gain focus or intercept keyboard input dialog behaviour parameter isfocusable = true isfocusable = false isoutsidetouchable = true dismisses on outside touch ( setcanceledontouchoutside(true) ) dialog is focusable by default dialog does not dismiss on outside touch and might not behave as expected since dialogs are typically focusable isoutsidetouchable = false does not dismiss on outside touch ( setcanceledontouchoutside(false) ) dialog remains focusable and can intercept input events dialog does not dismiss on outside touch and might not behave as expected due to the lack of focusability example of fragmentlayout r id cmpcontainer is a framelayout which could look like this in the activity layout xml in layout/{your activity} xml preventing the back action when the ui is displayed to prevent the closure of the ui, you need to override the onbackpressed function and check whether the cmp (consent management platform) is being displayed to verify that the cmp ui is shown, you can rely on the previously shown callbacks inside your activity class override fun onbackpressed() { if (iscmpopen) { return } super onbackpressed() } sdk apis cmp class constructors cmp(context context) description initializes the cmp with the specified context and the id of the content view parameters context the context of the application/activity public methods run(context context, cmpconfig cmpconfig) description runs the cmp with the provided configuration parameters context the context of the application/activity cmpconfig the configuration object for the cmp usage this method initializes and starts the cmp with the specified configuration shownotice(activity activity) description displays the cmp window to ask for user consent parameters activity the activity context where the cmp window will be displayed usage call this method to prompt the user for consent using the cmp window cmpconfig class constructors cmpconfig(id string, appname string, callbacks cmpcallbacks, debug boolean, retryconfig retryconfig) description constructs a configuration object for the cmp parameters id the id of the cmp appname the name of the application callbacks callback functions for cmp events debug for debugging purpose retryconfig for configuring the parameters available by the retry mechanism retryconfig class constructors retryconfig(maxretries int, retrydelay int, retriesbackofffactor double, timeout long) description constructs a configuration object for the retry mechanism that fetch the cmp parameters maxretries the maximum number of retry attempts default is 3 retrydelay the delay (in milliseconds) between consecutive retry attempts default is 200 retriesbackofffactor the factor by which the retry delay should be multiplied for exponential backoff default is 1 3 timeout the maximum duration (in milliseconds) within which the retry attempts must complete default is 7500 cmpcallbacks interface methods onconsentreadycallback() description callback function invoked when consent is ready note below, you will find the documentation on the available implementations of the consentapiinterface oncmpuiclosedcallback() description callback function invoked when the cmp window is closed oncmpuiopencallback() description callback function invoked when the cmp window is opened onerrorcallback(error string) description callback function invoked when an error occurs parameters error description of the error ongoogleconsentmodecallback(consentmap map\<int, int>) description callback function invoked when the google consent mapping is ready parameters consentmap map containing consent mappings pubconsent consentapiinterface using the api exposed through onconsentreadycallback , you can check which of the following implementations are available using the getcmptype() method (this choice depends on the configuration saved through the pubconsent configurator) below, we present the apis for each cmp type we offer the following methods are accessible via the instance consentapiinstance any pubconsent consentapiinterface , available as a parameter in the callback onconsentreadycallback api for cmptype tcf v2 gdpr when consent is related to the tcf cmp (i e , consentapiinterface getcmptype() == cmptype tcf v2 gdpr ), the following apis are available isvendorconsentenabled(vendorid int) boolean description checks if consent is enabled for a specific vendor parameters vendorid the vendor id to check consent for returns true if consent is granted for the specified vendor, otherwise false usage use this method to determine if consent has been granted for a specific vendor ispurposeconsentenabled(purposeid int) boolean description checks if consent is enabled for a specific purpose parameters purposeid the purpose id to check consent for returns true if consent is granted for the specified purpose, otherwise false usage use this method to determine if consent has been granted for a specific purpose isfeaturecookiesenabled() boolean description checks if consent is enabled for feature cookies returns true if consent is granted for feature cookies, otherwise false usage use this method to determine if consent has been granted for feature cookies isuserexperiencecookiesenabled() boolean description checks if consent is enabled for user experience cookies returns true if consent is granted for user experience cookies, otherwise false usage use this method to determine if consent has been granted for user experience cookies ismeasurementcookiesenabled() boolean description checks if consent is enabled for measurement cookies returns true if consent is granted for measurement cookies, otherwise false usage use this method to determine if consent has been granted for measurement cookies getgoogleconsentmode() map\<googleconsentmodetype, googleconsentmodestatus>? description retrieves the status of google consent mode for the supported consent types returns a map containing consent types ( googleconsentmodetype ) and their respective statuses ( googleconsentmodestatus ) returns null if no configuration is available usage use this method to obtain the consent status related to google consent mode and determine whether consent has been granted, denied, or is unknown for each consent type api for cmptype google consent mode when consent is related to the cmp based only on google consent mode (i e , consentapiinterface getcmptype() == cmptype google consent mode ), the following api is available getgoogleconsentmode() map\<googleconsentmodetype, googleconsentmodestatus>? description retrieves the status of google consent mode for the supported consent types returns a map containing consent types ( googleconsentmodetype ) and their respective statuses ( googleconsentmodestatus ) returns null if no configuration is available usage use this method to obtain the consent status related to google consent mode and determine whether consent has been granted, denied, or is unknown for each consent type troubleshooting proguard bugs proguard può talvolta offuscare i nomi delle classi o rimuovere i metodi che vengono richiamati dinamicamente tramite reflection per risolvere questo problema, è necessario specificare le classi e i metodi che devono rimanere intatti nel file di configurazione di proguard utilizzando la direttiva keep