So now, after we’ve described the Bindings Libraries creation process for Android and iOS, it’s time to show a real working example creation.
1. Usercentrics SDK working example
In SABOMobile IT, we use Xamarin Bindings for Usercentrics In-App SDK. Usercentrics is a Consent Management Platform to get GDPR, CCPA, LGPD compliant for websites and apps. Our goal was to show consent dialog to user in our Xamarin.Androidand Xamarin.iOS app and store it in central consent storage for both web and apps.
Usercentrics guys offer their SDK written on the Kotlin multiplatform, so the Android package is in the Kotlin language and the iOS package is in the transformed Objective-C language.
1.1.
Android bindings library
After all the steps described above, we’ve ended up with a Xamarin bindings library of Usercentrics for Android (Picture)
Whereas in the Additions folder, there are almost all missing empty implementations of interfaces created during transformation (which is performed during the build process), Usercentrics.cs is a partial class extending the original transformed com.usercentrics.sdk.usercentrics object with C# implementation of the Kotlin native IFunction event.

bindings library for Usercentrics SDK
In the Jars folder, you can see the original usercentrics-1.12.0.aar Android package (with Build Action set to “LibraryProjectZip”) and necessary third party .jar references used internally by the .aar package.For all .jar files, build action in Visual Studio is set to“EmbededReferenceJar”.
In the Transforms folder, EnumFields.xml and EnumMethods.xml are empty. Metadata.xml needs the following transformation to compile the Android Bindings Library without build errors:
{% c-block language="xml" %}
<metadata>
<attrpath="/api/package[@name='com.usercentrics.sdk.models.tcf']/class[@name='TCFFirstLayerDescription']/constructor[@name='TCFFirstLayerDescription' and count(parameter)=3 and parameter[1][@type='java.lang.String'] andparameter[2][@type='java.lang.String'] and parameter[3][@type='java.lang.String']]/parameter[@name='default']" name="name">defaultStr</attr>
<attrpath="/api/package[@name='com.usercentrics.sdk.models.tcf']/class[@name='TCFFirstLayerDescription']/method[@name='copy' and count(parameter)=3 and parameter[1][@type='java.lang.String'] andparameter[2][@type='java.lang.String'] andparameter[3][@type='java.lang.String']]" name="name">defaultStr</attr>
<attrpath="/api/package[@name='com.usercentrics.sdk.models.tcf']/class[@name='TCFFirstLayerDescription']/method[@name='defaultStr' and count(parameter)=3 and parameter[1][@type='java.lang.String'] and parameter[2][@type='java.lang.String'] and parameter[3][@type='java.lang.String']]/parameter[@name='default']" name="name">defaultStr</attr>
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='CategoryProps']/constructor[@name='CategoryProps' and count(parameter)=2 and parameter[1][@type='com.usercentrics.sdk.models.settings.UCCategory'] and parameter[2][@type='boolean']]/parameter[@name='checked']" name="name">isChecked</attr>
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='CategoryProps']/method[@name='copy' and count(parameter)=2 and parameter[1][@type='com.usercentrics.sdk.models.settings.UCCategory'] and parameter[2][@type='boolean']]/parameter[@name='checked']" name="name">isChecked</attr>
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='PurposeProps']/constructor[@name='PurposeProps' and count(parameter)=3 and parameter[1][@type='boolean'] and parameter[2][@type='boolean'] and parameter[3][@type='com.usercentrics.sdk.services.tcf.interfaces.TCFPurpose']]/parameter[@name='checked']" name="name">isChecked</attr>
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='PurposeProps']/method[@name='copy' and count(parameter)=3 and parameter[1][@type='boolean'] and parameter[2][@type='boolean'] and parameter[3][@type='com.usercentrics.sdk.services.tcf.interfaces.TCFPurpose']]/parameter[@name='checked']" name="name">isChecked</attr
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='SpecialFeatureProps']/constructor[@name='SpecialFeatureProps' and count(parameter)=2 and parameter[1][@type='boolean'] and parameter[2][@type='com.usercentrics.sdk.services.tcf.interfaces.TCFSpecialFeature']]/parameter[@name='checked']" name="name">isChecked</attr
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='SpecialFeatureProps']/method[@name='copy' and count(parameter)=2 and parameter[1][@type='boolean'] and parameter[2][@type='com.usercentrics.sdk.services.tcf.interfaces.TCFSpecialFeature']]/parameter[@name='checked']" name="name">isChecked</attr
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='StackProps']/constructor[@name='StackProps' and count(parameter)=2 and parameter[1][@type='boolean'] and parameter[2][@type='com.usercentrics.sdk.services.tcf.interfaces.TCFStack']]/parameter[@name='checked']" name="name">isChecked</attr>
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='StackProps']/method[@name='copy' and count(parameter)=2 and parameter[1][@type='boolean'] and parameter[2][@type='com.usercentrics.sdk.services.tcf.interfaces.TCFStack']]/parameter[@name='checked']" name="name">isChecked</attr
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='VendorProps']/constructor[@name='VendorProps' and count(parameter)=3 and parameter[1][@type='boolean'] and parameter[2][@type='boolean'] and parameter[3][@type='com.usercentrics.sdk.services.tcf.interfaces.TCFVendor']]/parameter[@name='checked']" name="name">isChecked</attr>
<attrpath="/api/package[@name='com.usercentrics.sdk']/class[@name='VendorProps']/method[@name='copy' and count(parameter)=3 and parameter[1][@type='boolean'] and parameter[2][@type='boolean']and parameter[3][@type='com.usercentrics.sdk.services.tcf.interfaces.TCFVendor']]/parameter[@name='checked']" name="name">isChecked</attr>
<remove-node path="/api/package[@name='com.usercentrics.sdk']/class[@name='ApiLabels']/constructor"/>
</metadata>
{% c-block-end %}
1.2. iOS Bindings library
We used this command to run the Sharpie Utility, which transforms the Objective-C header .h file to the corresponding ApiDefinitions.cs file (Picture).
{% c-block language="xml" %}
sharpie bind -sdkiphoneos14.5 ./Usercentrics.framework/Headers/Usercentrics.h -namespace Usercentrics -scope Usercentrics.framework/Headers -c -F
{% c-block-end %}
This means that we’ve bound the library corresponding to the iPhone OS 14.5 version, specifying namespace to “Usercentrics”.
The resulting Structs.cs file is empty and ApiDefinitions.cs is a pretty huge file with almost 12 thousand lines of code definition.


1.3. Usercentrics SDK usage in Xamarin application
After we produce Xamarin bindings libraries both for Android and for iOS, we just wrap the SDK calls into platform specific services which implement the interface defined in the shared Xamarin.net standard project.
After this, we create our own UI for user consent interaction which calls the Usercentrics SDK in the background for storing and refreshing consents in the cloud.

1.5. Conclusion
What we’ve learned in this article: Creation of a Xamarin Bindings Library gives us the freedom to use .NET for native mobile apps, even if we have to use some native dependencies. The creation itself is a complex problem with platform / language specific pitfalls, but achieving this ability means a lot for Xamarin / MAUI developers. It raises their potential to work on any mobile apps related problem.
In SABOMobile IT, creation of the Xamarin Bindings Library enables us to offer requested functionality for our customers and allows us to fulfill all clients’ needs to the fullest.
Thank you for reading!
Luboš Brát, Senior software developer @ SABO Mobile IT
References used in article
1) https://www.mono-project.com/docs/advanced/runtime/
2) https://docs.microsoft.com/en-us/xamarin/get-started/what-is-xamarin
3) https://www.xamboy.com/2020/07/20/creating-a-xamarin-binding-library-for-ios-and-android-part-1/
4) https://docs.microsoft.com/en-us/xamarin/android/platform/binding-java-library/
5) http://java-decompiler.github.io/
6) https://docs.usercentrics.com/#/in-app-sdk
7) https://www.w3schools.com/xml/xpath_syntax.asp
8) https://docs.microsoft.com/en-us/xamarin/cross-platform/macios/binding/objective-sharpie/
9) https://debruyn.dev/2016/creating-a-xamarin.ios-binding-project-for-dummies/
10) https://docs.microsoft.com/en-us/xamarin/xamarin-forms/deploy-test/hot-restart
Read previous: Xamarin Bindings Libraries, an Android part (1/3)
Read previous: Xamarin Bindings Libraries, and iOS part (2/3)

Luboš is an experienced .NET developer (web and mobile apps) very familiar with SQL and DevOps. He developed a lot of web applications used worldwide by industry and the academical world. He holds a bachelor’s degree in applied physics and astrophysics. Likes bowling, rides e-mountainbike, skis and plays the violin.





SABO IT
More articles




