Nachdem wir also den Prozess der Erstellung von Bindungsbibliotheken für Android und iOS beschrieben haben, ist es nun an der Zeit, die Erstellung eines echten Arbeitsbeispiels zu zeigen.
Bei SABO MobileIT haben wir Xamarin Bindings für Usercentrics In-App SDK verwendet. Usercentrics ist eine Consent Management Plattform (CMP), um GDPR-, CCPA- und LGPD-konforme Websites und Apps zu erstellen. Unser Ziel war es, dem Benutzer in unserer Xamarin.Android- und Xamarin.iOS-App einen Einwilligungsdialog zu zeigen und diesen in einem zentralen Einwilligungsspeicher für Web und Apps zu speichern.
Das Team von Usercentrics bietet ihr in Kotlin Multiplatform geschriebenes SDK an, d. h. das Android-Paket ist in Kotlin geschrieben und das iOS-Paket in der umgewandelten Sprache Objective-C.
Nach all den oben beschriebenen Schritten haben wir am Ende eine solche Xamarin-Bindungsbibliothek von Usercentrics für Android (Abbildung).
Im Ordner Additions fehlen fast alle leeren Implementierungen von Schnittstellen, die während der Transformation (die während des Build-Prozesses durchgeführt wird) erstellt wurden. Usercentrics.cs ist eine Teilklasse, die das ursprüngliche transformierte com.usercentrics.sdk.usercentrics-Objekt um eine C#-Implemen-tierung des nativen Kotlin IFunction Ereignisses erweitert.
Im Jars-Ordner finden Sie das ursprüngliche usercentrics-1.12.0.aar-Android-Paket (mit derBuild-Aktion "LibraryProjectZip") und die notwendigen .jar-Referenzen von Drittanbietern, die intern von dem .aar-Paket verwendet werden. Für alle .jar-Dateien ist die Build Action in Visual Studio auf "EmbededReferenceJar"eingestellt.
In Transforms Ordner, EnumFields.xml und EnumMethods.xml sind leer. Metadata.xml benötigt die folgende Transformation, um die Android Bindungsbibliothek ohne Build-Fehler zu kompilieren:
{% 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 %}
Wir haben diesen Befehl verwendet, um die SharpieUtility auszuführen, das die Objective-C-Header-Datei .h in die entsprechende ApiDefinitions.cs-Datei umwandelt (Abbildung 9)
{% c-block language="xml" %}
sharpie bind -sdkiphoneos14.5 ./Usercentrics.framework/Headers/Usercentrics.h -namespaceUsercentrics -scope Usercentrics.framework/Headers -c -F
{% c-block-end %}
Das heißt, wir haben die Bibliothek entsprechend der iPhone OS 14.5 Version gebunden, indem wir den Namespace auf "Usercentrics" festgelegt haben.
Die resultierendeDatei Structs.cs ist leer und ApiDefinitions.cs ist eine ziemlich große Datei mit fast 12.000 Zeilen Code Definition.
Nun liegen die Xamarin Bindungsbibliotheken sowohl für Android als auch für iOS vor und wir haben dieSDK-Aufrufe einfach in plattformspezifische Dienste verpackt, die die im gemeinsamen.NET Standard Projekt definierte Schnittstelle implementieren.
Danach haben wir unsere eigene Benutzeroberfläche für die Interaktion mit dem Benutzer erstellt und rufen im Hintergrund Usercentrics SDK auf, um die Zustimmungen in der Cloud zu speichern und zu aktualisieren.
Was wir in diesem Artikel gelernt haben? DieErstellung der Xamarin Bindungsbibliothek gibt uns die Freiheit, .NET fürnative mobile Apps zu verwenden, auch wenn wir einige native Abhängigkeiten verwenden müssen. Die Erstellung selbst ist ein komplexes Problem mit plattform- / sprachspezifischenFallstricken, aber das Erreichen dieser Fähigkeit bedeutet viel für Xamarin / MAUIEntwickler. Es erhöht ihr Potenzial bei der Arbeit an jedem Problem imZusammenhang mit mobilen Anwendungen.
Bei SABO MobileIT ermöglicht uns die Erstellung der Xamarin Bindings Library, die gewünschte Funktionalität für unsere Kunden anzubieten und alle Kundenanforderungen im vollem Umfang zu erfüllen.
Vielen Dank fürs Lesen!
Luboš Brát, Senior Softwareentwickler @ SABO Mobile IT
Im Artikel verwendete Referenzen
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
VorherigenAbschnitt lesen: Xamarin Bindings Libraries, ein Android-Teil (1/3)
Vorherigen Abschnitt lesen: XamarinBindungsbibliotheken, ein iOS-Teil (2/3)