Sdílet prostřednictvím


Návod: Vytvoření vazby knihovny Android Kotlin

Důležité

V současné době prošetřujeme využití vlastních vazeb na platformě Xamarin. Pokud chcete informovat budoucí úsilí o rozvoj, využijte tento průzkum .

Xamarin umožňuje vývojářům mobilních aplikací vytvářet mobilní aplikace nativní pro různé platformy pomocí sady Visual Studio a jazyka C#. Komponenty sady Sdk platformy Android můžete používat předem, ale v mnoha případech také chcete používat sady SDK třetích stran napsané pro danou platformu a Xamarin to umožňuje provádět prostřednictvím vazeb. Aby bylo možné do aplikace Xamarin.Android začlenit architekturu androidu třetí strany, musíte pro ni vytvořit vazbu Xamarin.Android, abyste ji mohli použít ve svých aplikacích.

Platforma Android spolu s nativními jazyky a nástroji se neustále vyvíjí, včetně nedávného zavedení jazyka Kotlin, který se nakonec nastaví na nahrazení Javy. Existuje řada 3d party SAD SDK, které už byly migrovány z Javy do Kotlinu a představují nové výzvy. I když je proces vazby Kotlin podobný Javě, vyžaduje další kroky a nastavení konfigurace k úspěšnému sestavení a spuštění v rámci aplikace Xamarin.Android.

Cílem tohoto dokumentu je nastínit obecný přístup k řešení tohoto scénáře a poskytnout podrobný průvodce jednoduchým příkladem.

Pozadí

Kotlin byl vydán v únoru 2016 a byl umístěn jako alternativa ke standardnímu kompilátoru Java do Android Studia do roku 2017. Později v roce 2019 google oznámil, že programovací jazyk Kotlin se stal upřednostňovaným jazykem pro vývojáře aplikací pro Android. Přístup k vazbám vysoké úrovně se podobá procesu vazby běžných knihoven Java s několika důležitými kroky specifickými pro Kotlin.

Požadavky

K dokončení tohoto návodu budete potřebovat:

Vytvoření nativní knihovny

Prvním krokem je vytvoření nativní knihovny Kotlin pomocí Android Studia. Knihovnu obvykle poskytuje vývojář třetí strany nebo je k dispozici v úložišti Maven společnosti Google a dalších vzdálených úložištích. Například v tomto kurzu se vytvoří vazba pro knihovnu Kotlin pro výběr bublin:

GitHub BubblePicker demo

  1. Stáhněte zdrojový kód z GitHubu pro knihovnu a rozbalte ho do místní složky Bubble-Picker.

  2. Spusťte Android Studio a vyberte Možnost Otevřít existující nabídku projektu Android Studio a zvolte místní složku Pro výběr bublin:

    Android Studio Open Project

  3. Ověřte, že je Android Studio aktuální, včetně Gradle. Zdrojový kód lze úspěšně sestavit na Android Studiu verze 3.5.3, Gradle v5.4.1. Pokyny k aktualizaci Gradle na nejnovější verzi Gradle najdete tady.

  4. Ověřte, že je nainstalovaná požadovaná sada Android SDK. Zdrojový kód vyžaduje Sadu Android SDK v25. Otevřete možnost nabídky Správce sady Sdk Nástroje > pro instalaci komponent sady SDK.

  5. Aktualizujte a synchronizujte hlavní konfigurační soubor build.gradle umístěný v kořenové složce projektu:

    • Nastavení verze Kotlin na 1.3.10

      buildscript {
          ext.kotlin_version = '1.3.10'
      }
      
    • Zaregistrujte výchozí úložiště Maven společnosti Google, aby bylo možné vyřešit závislost knihovny podpory:

      allprojects {
          repositories {
              jcenter()
              maven {
                  url "https://maven.google.com"
              }
          }
      }
      
    • Jakmile se konfigurační soubor aktualizuje, je mimo synchronizaci a Gradle zobrazí tlačítko Synchronizovat, stiskněte ho a počkejte na dokončení procesu synchronizace:

      Android Studio Gradle Sync Now

      Tip

      Mezipaměť závislostí Gradle může být poškozená, někdy k tomu dochází po vypršení časového limitu síťového připojení. Znovu stáhněte závislosti a synchronizační projekt (vyžaduje síť).

      Tip

      Stav procesu sestavení Gradle (démon) může být poškozený. Tento problém může vyřešit zastavení všech démon Gradle. Zastavení procesů sestavení Gradle (vyžaduje restartování). V případě poškozenýchprocesůch

      Tip

      Váš projekt může používat modul plug-in třetí strany, který není kompatibilní s ostatními moduly plug-in v projektu nebo verzí Gradle požadované projektem.

  6. Otevřete nabídku Gradle na pravé straně, přejděte do nabídky úkoly bubblepickeru>, spusťte úlohu sestavení tak, že na ni poklepete a počkáte na dokončení procesu sestavení:

    Android Studio Gradle Execute Task

  7. Otevřete prohlížeč souborů kořenové složky a přejděte do složky sestavení: Bubble-Picker -> bubblepicker - build ->> outputs -> aar, uložte soubor bubblepicker-release.aar jako bubblepicker-v1.0.aar, tento soubor se použije později v procesu vazby:

    Android Studio AAR Output

Soubor AAR je archiv pro Android, který obsahuje zkompilovaný zdrojový kód a prostředky Kotlin, které Android vyžaduje ke spuštění aplikace pomocí této sady SDK.

Příprava metadat

Druhým krokem je příprava souboru transformace metadat, který používá Xamarin.Android ke generování příslušných tříd jazyka C#. Projekt vazby Xamarin.Android vyhledá všechny nativní třídy a členy z daného archivu Androidu a následně vygeneruje soubor XML s příslušnými metadaty. Ručně vytvořený soubor transformace metadat se pak použije na dříve vygenerovaný směrný plán a vytvoří konečný definiční soubor XML použitý k vygenerování kódu jazyka C#.

Metadata používají syntaxi XPath a používá ho Generátor vazeb k ovlivnění vytváření sestavení vazby. Další informace o transformacích, které je možné použít, najdete v článku o metadatech vazby Java:

  1. Vytvořte prázdný soubor Metadata.xml :

    <?xml version="1.0" encoding="UTF-8"?>
    <metadata>
    </metadata>
    
  2. Definování transformací XML:

  • Nativní knihovna Kotlin má dvě závislosti, které nechcete vystavit světu jazyka C#, definují dvě transformace, které je úplně ignorují. Důležité je říci, že nativní členy nebudou odstraněny z výsledného binárního souboru, nebudou generovány pouze třídy jazyka C#. Dekompiler Jazyka Java lze použít k identifikaci závislostí. Spusťte nástroj a otevřete soubor AAR vytvořený dříve, proto se zobrazí struktura archivu Androidu, která bude odrážet všechny závislosti, hodnoty, prostředky, manifest a třídy:

    Java Decompiler Dependencies

    Transformace pro přeskočení zpracování těchto balíčků jsou definovány pomocí pokynů XPath:

    <remove-node path="/api/package[starts-with(@name,'org.jbox2d')]" />
    <remove-node path="/api/package[starts-with(@name,'org.slf4j')]" />
    
  • Nativní BubblePicker třída má dvě metody getBackgroundColor a setBackgroundColor následující transformace ji změní na vlastnost jazyka C# BackgroundColor :

    <attr path="/api/package[@name='com.igalata.bubblepicker.rendering']/class[@name='BubblePicker']/method[@name='getBackground' and count(parameter)=0]" name="propertyName">BackgroundColor</attr>
    <attr path="/api/package[@name='com.igalata.bubblepicker.rendering']/class[@name='BubblePicker']/method[@name='setBackground' and count(parameter)=1 and parameter[1][@type='int']]" name="propertyName">BackgroundColor</attr>
    
  • Nepodepsané typy UInt, UShort, ULong, UByte vyžadují zvláštní zpracování. U těchto typů Kotlin změní názvy metod a typy parametrů automaticky, což se projeví ve vygenerovaném kódu:

    public open fun fooUIntMethod(value: UInt) : String {
        return "fooUIntMethod${value}"
    }
    

    Tento kód je zkompilován do následujícího bajtového kódu Javy:

    @NotNull
    public String fooUIntMethod-WZ4Q5Ns(int value) {
    return "fooUIntMethod" + UInt.toString-impl(value);
    }
    

    Kromě toho, související typy, jako UIntArray, UShortArray, ULongArray, UByteArray jsou také ovlivněny Kotlin. Název metody se změní tak, aby zahrnoval další příponu a parametry se změní na pole prvků podepsaných verzí stejných typů. V příkladu pod parametrem typu UIntArray se automaticky převede na int[] a název metody se změní z fooUIntArrayMethod na fooUIntArrayMethod--ajY-9A. Druhá je zjištěna nástroji Xamarin.Android a vygenerována jako platný název metody:

    public open fun fooUIntArrayMethod(value: UIntArray) : String {
        return "fooUIntArrayMethod${value.size}"
    }
    

    Tento kód je zkompilován do následujícího bajtového kódu Javy:

    @NotNull
    public String fooUIntArrayMethod--ajY-9A(@NotNull int[] value) {
        Intrinsics.checkParameterIsNotNull(value, "value");
        return "fooUIntArrayMethod" + UIntArray.getSize-impl(value);
    }
    

    Aby bylo možné ho pojmenovat smysluplně, můžete do Metadata.xml přidat následující metadata, která aktualizují název zpět tak, aby byl původně definovaný v kódu Kotlin:

    <attr path="/api/package[@name='com.microsoft.simplekotlinlib']/class[@name='FooClass']/method[@name='fooUIntArrayMethod--ajY-9A']" name="managedName">fooUIntArrayMethod</attr>
    

    V ukázce BubblePickeru nejsou žádní členové používající nepodepsané typy, takže nejsou potřeba žádné další změny.

  • Členy Kotlinu s obecnými parametry se ve výchozím nastavení transformují na parametry Javy.Lang.Object Typ. Například metoda Kotlin má obecný parametr <T>:

    public open fun <T>fooGenericMethod(value: T) : String {
    return "fooGenericMethod${value}"
    }
    

    Po vygenerování vazby Xamarin.Android se metoda zobrazí v jazyce C# následujícím způsobem:

    [Register ("fooGenericMethod", "(Ljava/lang/Object;)Ljava/lang/String;", "GetFooGenericMethod_Ljava_lang_Object_Handler")]
    [JavaTypeParameters (new string[] {
        "T"
    })]
    
    public virtual string FooGenericMethod (Java.Lang.Object value);
    

    Vazby Xamarin.Android nepodporují obecné typy Java a Kotlin, takže se vytvoří zobecněná metoda jazyka C#pro přístup k obecnému rozhraní API. Jako alternativní řešení můžete vytvořit obálkovou knihovnu Kotlin a vystavit požadovaná rozhraní API silným typem bez obecných typů. Případně můžete vytvořit pomocné rutiny na straně jazyka C#, které budou problém řešit stejným způsobem prostřednictvím rozhraní API se silnými typy.

    Tip

    Při transformaci metadat se na vygenerovanou vazbu dají použít všechny změny. Článek o vazbě knihovny Java vysvětluje podrobnosti o tom, jak se metadata generují a zpracovávají.

Vytvoření knihovny vazeb

Dalším krokem je vytvoření projektu vazby Xamarin.Android pomocí šablony vazby sady Visual Studio, přidání požadovaných metadat, nativních odkazů a následné sestavení projektu pro vytvoření spotřební knihovny:

  1. Otevřete Visual Studio pro Mac a vytvořte nový projekt knihovny vazeb Xamarin.Android, pojmenujte ho v tomto případě testBubblePicker.Binding a dokončete průvodce. Šablona vazby Xamarin.Android se nachází v následující cestě: Knihovna vazeb knihovny > Androidu>:

    Visual Studio Create Binding

    Ve složce Transformace existují tři hlavní transformační soubory:

    • Metadata.xml – Umožňuje provádět změny v konečném rozhraní API, například změnit obor názvů vygenerované vazby.
    • EnumFields.xml – obsahuje mapování mezi int konstantami Jazyka Java a výčty jazyka C#.
    • EnumMethods.xml – Umožňuje změnit parametry metody a vracet typy z int konstant Jazyka Java do výčtů jazyka C#.

    Vyprázdněte soubory EnumFields.xml a EnumMethods.xml a aktualizujte Metadata.xml , aby se definovaly transformace.

  2. Nahraďte existující soubor Transformací/Metadata.xml souborem Metadata.xml vytvořeným v předchozím kroku. V okně vlastností ověřte, že je akce sestavení souboru nastavená na TransformationFile:

    Visual Studio Metadata

  3. Přidejte soubor bubblepicker-v1.0.aar , který jste vytvořili v kroku 1, do projektu vazby jako nativní odkaz. Pokud chcete přidat odkazy na nativní knihovnu, otevřete finder a přejděte do složky s archivem Androidu. Přetáhněte archiv do složky Jars v Průzkumník řešení. Alternativně můžete použít možnost Přidat místní nabídku ve složce Jars a zvolit Existující soubory.... Zvolte, že chcete soubor zkopírovat do adresáře pro účely tohoto názorného postupu. Nezapomeňte ověřit, že je akce sestavení nastavená na LibraryProjectZip:

    Visual Studio Native Reference

  4. Přidejte odkaz na balíček NuGet Xamarin.Kotlin.StdLib. Tento balíček je vazbou pro standardní knihovnu Kotlin. Bez tohoto balíčku bude vazba fungovat pouze v případě, že knihovna Kotlin nepoužívá žádné konkrétní typy Kotlin, jinak všichni tito členové nebudou vystaveni jazyku C# a žádná aplikace, která se pokusí tuto vazbu využívat, dojde k chybě za běhu.

    Tip

    Z důvodu omezení Xamarin.Android je možné pro každý projekt vazby přidat nástroje pro vazby pouze jeden archiv Androidu (AAR). Pokud je potřeba zahrnout více souborů AAR, vyžaduje se více projektů Xamarin.Android, jeden pro každou AAR. Pokud by se jednalo o tento názorný postup, předchozí čtyři akce tohoto kroku by se musely opakovat pro každý archiv. Jako alternativní možnost je možné ručně sloučit více archivů Androidu jako jeden archiv a v důsledku toho můžete použít jeden projekt vazby Xamarin.Android.

  5. Poslední akcí je sestavení knihovny a provedení žádné chyby kompilace. V případě chyb kompilace je možné je vyřešit a zpracovat pomocí souboru Metadata.xml, který jste vytvořili dříve přidáním metadat transformace XML, která přidají, odeberou nebo přejmenují členy knihovny.

Využití knihovny vazeb

Posledním krokem je využití knihovny vazeb Xamarin.Android v aplikaci Xamarin.Android. Vytvořte nový projekt Xamarin.Android, přidejte odkaz na knihovnu vazeb a vykreslujte uživatelské rozhraní pro výběr bublin:

  1. Vytvořte projekt Xamarin.Android. Jako výchozí bod použijte aplikaci pro Android App> pro Android > a vyberte možnost Nejnovější a Nejlepší jako cílové platformy, abyste se vyhnuli problémům s kompatibilitou. Tento projekt cílí na všechny následující kroky:

    Visual Studio Create App

  2. Přidejte odkaz na projekt vazby nebo přidejte odkaz na knihovnu DLL vytvořenou dříve:

    Visual Studio Add Binding Reference.png

  3. Přidejte odkaz na balíček NuGet Xamarin.Kotlin.StdLib, který jste přidali do projektu vazby Xamarin.Android dříve. Přidává podporu pro všechny konkrétní typy Kotlin, které potřebují předat modul runtime. Bez tohoto balíčku je možné aplikaci zkompilovat, ale dojde k chybě za běhu:

    Visual Studio Add StdLib NuGet

  4. BubblePicker Přidejte ovládací prvek do rozložení androidu pro MainActivity. Otevřete soubor testBubblePicker/Resources/layout/content_main.xml a připojte řídicí uzel BubblePicker jako poslední prvek kořenového ovládacího prvku RelativeLayout:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout …>
        …
        <com.igalata.bubblepicker.rendering.BubblePicker
            android:id="@+id/picker"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:backgroundColor="@android:color/white" />
    </RelativeLayout>
    
  5. Aktualizujte zdrojový kód aplikace a přidejte logiku inicializace do MainActivitysady SDK pro výběr bublin:

    protected override void OnCreate(Bundle savedInstanceState)
    {
        ...
        var picker = FindViewById<BubblePicker>(Resource.Id.picker);
        picker.BubbleSize = 20;
        picker.Adapter = new BubblePickerAdapter();
        picker.Listener = new BubblePickerListener(picker);
        ...
    }
    

    BubblePickerAdapter a BubblePickerListener jsou dvě třídy, které se mají vytvořit od nuly, které zpracovávají data bublin a interakci s ovládacími prvky:

    public class BubblePickerAdapter : Java.Lang.Object, IBubblePickerAdapter
    {
        private List<string> _bubbles = new List<string>();
        public int TotalCount => _bubbles.Count;
        public BubblePickerAdapter()
        {
            for (int i = 0; i < 10; i++)
            {
                _bubbles.Add($"Item {i}");
            }
        }
    
        public PickerItem GetItem(int itemIndex)
        {
            if (itemIndex < 0 || itemIndex >= _bubbles.Count)
                return null;
    
            var result = _bubbles[itemIndex];
            var item = new PickerItem(result);
            return item;
        }
    }
    
    public class BubblePickerListener : Java.Lang.Object, IBubblePickerListener
    {
        public View Picker { get; }
        public BubblePickerListener(View picker)
        {
            Picker = picker;
        }
    
        public void OnBubbleDeselected(PickerItem item)
        {
            Snackbar.Make(Picker, $"Deselected: {item.Title}", Snackbar.LengthLong)
                .SetAction("Action", (Android.Views.View.IOnClickListener)null)
                .Show();
        }
    
        public void OnBubbleSelected(PickerItem item)
        {
            Snackbar.Make(Picker, $"Selected: {item.Title}", Snackbar.LengthLong)
            .SetAction("Action", (Android.Views.View.IOnClickListener)null)
            .Show();
        }
    }
    
  6. Spusťte aplikaci, která by měla vykreslit uživatelské rozhraní pro výběr bublin:

    BubblePicker demo

    Ukázka vyžaduje další kód pro vykreslení stylu prvků a zpracování interakcí, ale BubblePicker ovládací prvek byl úspěšně vytvořen a aktivován.

Gratulujeme! Úspěšně jste vytvořili aplikaci Xamarin.Android a knihovnu vazeb, která využívá knihovnu Kotlin.

Teď byste měli mít základní aplikaci Xamarin.Android, která používá nativní knihovnu Kotlin prostřednictvím knihovny vazeb Xamarin.Android. Tento názorný postup záměrně používá základní příklad k lepšímu zdůraznění klíčových konceptů, které se zavádějí. V reálných scénářích budete pravděpodobně muset zveřejnit větší počet rozhraní API a použít na ně transformace metadat.