Xamarin.Android binding projekt migrálása

A .NET-ben nincs fogalma egy Android-kötési projektről külön projekttípusként. A Xamarin.Android kötési projektekben működő MSBuild elemcsoportok vagy buildműveletek bármelyike támogatott androidos .NET-alkalmazáson vagy -táron keresztül.

Xamarin.Android kötéskódtár áttelepítése androidos .NET-osztálytárba:

  1. A Visual Studióban hozzon létre egy új Android Java Library Binding-projektet a Xamarin.Android kötésprojekt nevével:

    Képernyőkép androidos Java-kódtár-kötési projekt létrehozásáról a Visual Studióban.

    A projektfájl megnyitása megerősíti, hogy .NET SDK-stílusú projektje van:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net8.0-android</TargetFramework>
        <SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
      </PropertyGroup>
    </Project>
    

    Megjegyzés:

    Az Android-kötéstár projektfájlja megegyezik egy Android-osztálytár projektfájljának fájlával.

  2. Adja hozzá a Java Archívumot (JAR) vagy az Android Archivet (AAR) a projekthez, és győződjön meg arról, hogy a buildelési művelet AndroidLibrary értékre van állítva.

  3. Másolja ki az átalakításokat vagy kiegészítéseket a Xamarin.Android kötéstárból.

Nem támogatott örökölt beállítások

A következő örökölt beállítások már nem támogatottak. A támogatott alternatívák már évek óta elérhetők, és a leggördülékenyebb migrálási lehetőség az, ha frissíti és teszteli az aktuális projektjeit ezekkel a lehetőségekkel, mielőtt migrálja őket a .NET-be.

AndroidClassParser

jar2xml már nem érvényes beállítás a $(AndroidClassParser) tulajdonsághoz. class-parse mostantól az alapértelmezett és csak a támogatott beállítás.

class-parse számos olyan új modern funkció előnyeit használja ki, amelyek nem érhetők el jar2xml, például:

  • Az osztálymódszerek automatikus paraméternevei (ha a Java-kód fordítása ezzel javac -parameterstörténik).
  • Kotlin-támogatás.
  • Statikus/alapértelmezett interfész tag (DIM) támogatás.
  • Java Nullable reference type (NRT) annotációk támogatása.

AndroidCodegenTarget

XamarinAndroid már nem érvényes beállítás a $(AndroidCodegenTarget) tulajdonsághoz. XAJavaInterop1 mostantól az alapértelmezett és csak a támogatott beállítás.

Ha kézzel kötött kód van a Additions fájlokban, amelyek a létrehozott kötési kóddal kommunikálnak, előfordulhat, hogy frissíteni kell, hogy kompatibilis legyen azokkal XAJavaInterop1.

Alapértelmezett fájlbefoglalás

A következő fájlstruktúra miatt:

Transforms/
    Metadata.xml
foo.jar

Transforms\*.xml fájlokat automatikusan @(TransformFile) elemként tartalmazza a rendszer, és a .jar/.aar fájlokat automatikusan @(AndroidLibrary) elemként tartalmazza. Ez köti a C#-típusokat a metaadat-javítások használatával talált foo.jar Java-típusokhoz Transforms\Metadata.xml.

Az Androidhoz kapcsolódó alapértelmezett fájlküldő viselkedést az AutoImport.props határozza meg. Ez a viselkedés letiltható androidos elemek esetén a $(EnableDefaultAndroidItems) tulajdonság falsebeállításával, vagy az összes alapértelmezett elembefoglalási viselkedés letiltható a $(EnableDefaultItems) tulajdonság falsebeállításával.

Nem kívánt .jar vagy .aar fájlok is szerepelhetnek az alapértelmezett helyettesítő karakterekben. A következő C#-fordítóhibák például egy AndroidStudio\gradle\wrapper\gradle-wrapper.jar véletlenül kötött fájlból erednek:

Org.Gradle.Cli.AbstractCommandLineConverter.cs(11,89): error CS0535: 'Download' does not implement interface member 'IDownload.Download(URI, File)'
Org.Gradle.Wrapper.Download.cs(10,60): error CS0535: 'AbstractCommandLineConverter' does not implement interface member 'ICommandLineConverter.Convert(ParsedCommandLine, Object)'

A probléma megoldásához eltávolíthatja az adott fájlt a projektfájlból:

<ItemGroup>
  <AndroidLibrary Remove="AndroidStudio\gradle\wrapper\gradle-wrapper.jar" />
</ItemGroup>

Másik lehetőségként kizárhatja az összes fájlt egy mappából:

<AndroidLibrary Remove="AndroidStudio\**\*" />

Új elemcsoportnevek

<AndroidLibrary> mostantól az összes .jar és .aar fájl számára ajánlott elemcsoport. A Xamarin.Androidban a következő elemcsoportokat használták, amelyek ehelyett az elem metaadataival érik el ugyanazt az eredményt:

Örökölt elemcsoport Új elemcsoport Elem metaadatai Örökölt projekttípus
AndroidAarLibrary AndroidLibrary Bind="false" Alkalmazás
AndroidJavaLibrary AndroidLibrary Bind="false" Alkalmazás- vagy osztálytár
EmbeddedJar AndroidLibrary nincs adat Kötelező projekt
EmbeddedReferenceJar AndroidLibrary Bind="false" Kötelező projekt
InputJar AndroidLibrary Pack="false" Kötelező projekt
LibraryProjectZip AndroidLibrary nincs adat Kötelező projekt

Fontolja meg azt a .aar fájlt vagy .jar fájlt, amelyben nem szeretne C#-kötést belevenni. Ez gyakori azokban az esetekben, amikor Java- vagy Kotlin-függőségekkel rendelkezik, amelyeket nem kell C#-ból hívnia. Ebben az esetben a Bind metaadatot a false értékre állíthatja. Alapértelmezés szerint a fájlt az alapértelmezett helyettesítő karakterek veszik fel. Az Update attribútumot is használhatja a Bind metaadatok beállításához.

<ItemGroup>
  <AndroidLibrary Update="foo.jar" Bind="false">
</ItemGroup>

Egy Android-osztálykódtár-projektben ez az eredményül kapott NuGet-csomagon belül terjesztené újra a .jar fájlt. Egy Android-alkalmazásprojektben ez a .jar fájl az eredményként kapott .apk vagy .aab a fájlba is belefoglalható. Egyik sem tartalmaz C#-kötést ehhez a Java-kódtárhoz.

Beágyazott JAR/AAR-fájlok

A Xamarin.Android keretében a Java .jar vagy .aar gyakran beágyazott erőforrásként szerepelt a bindingban .dll. Ez azonban lassú buildekhez vezetett, mivel mindegyiket .dll meg kell nyitni és be kell olvasni a Java-kódot. Ha megtalálják, a használathoz ki kell nyerni a lemezre.

A .NET-ben a Java-kód már nincs beágyazva a .dll. Az alkalmazás összeállítási folyamata automatikusan tartalmazza azokat a .jar vagy .aar fájlokat, amelyeket ugyanabban a könyvtárban talál, mint a hivatkozott .dll.

Ha egy projekt egy kötésre hivatkozik <PackageReference> vagy <ProjectReference>, akkor minden működik, és nincs szükség további szempontokra. Ha azonban egy projekt egy kötésre hivatkozik<Reference>, akkor a.jar/.aar-nek a.dll mellett kell lennie. Ez a következő referencia:

<Reference Include="MyBinding.dll" />

A következő példában szereplő könyvtár nem fog működni:

lib/
    MyBinding.dll

Ehelyett a könyvtárnak tartalmaznia kell a natív kódot is:

lib/
    MyBinding.dll
    mybinding.jar

Migrálási szempontok

Alapértelmezés szerint számos új funkció van beállítva, amelyek segítenek a Java-megfelelőiknek jobban megfelelő kötések létrehozásában. Ha azonban egy meglévő kötésprojektet migrál, ezek a funkciók olyan kötéseket hozhatnak létre, amelyek nem kompatibilisek az API-val a meglévő kötésekkel. A kompatibilitás fenntartása érdekében érdemes lehet letiltani vagy módosítani ezeket az új funkciókat.

Illesztőállandók

Hagyományosan a C# nem engedélyezte, hogy állandókat deklaráljunk egy interface-ben, ami egy gyakori minta a Java-ban.

public interface Foo {
     public static int BAR = 1;
}

Ezt a mintát korábban egy olyan alternatíva class létrehozásával támogatták, amely az állandókat tartalmazza:

public abstract class Foo : Java.Lang.Object
{
   public static int Bar = 1;
}

A C# 8-ban ezek az állandók a interface-ra kerülnek.

public interface IFoo
{
    public static int Bar = 1;
}

Ez azonban azt jelenti, hogy a meglévő kódtól függő alternatív osztály már nem jön létre.

Ha a $(AndroidBoundInterfacesContainConstants) tulajdonságot false értékre állítja a projektfájlban, ezzel visszaállítja az örökölt viselkedést.

Beágyazott felülettípusok

A C# hagyományosan nem engedélyezte, hogy beágyazott típusokat deklaráljunk egy interface-ban, amit a Java megenged.

public interface Foo {
     public class Bar { }
}

Ezt a mintát úgy támogatták, hogy a beágyazott típust egy legfelső szintű típusra helyezték át egy létrehozott névvel, amely az interfészből és a beágyazott típusnévből áll:

public interface IFoo { }

public class IFooBar : Java.Lang.Object { }

A C# 8 esetén a beágyazott típusok a interfacekövetkező helyre helyezhetők:

public interface IFoo
{
    public class Bar : Java.Lang.Object { }
}

Ez azonban azt jelenti, hogy a meglévő kódtól függő legfelső szintű osztály már nem jön létre.

Ha a $(AndroidBoundInterfacesContainTypes) tulajdonságot false értékre állítja a projektfájlban, ezzel visszaállítja az örökölt viselkedést.

Ha például hibrid megközelítést szeretne használni, hogy a meglévő beágyazott típusok felső szintű típusba legyenek áthelyezve, de a jövőbeli beágyazott típusok beágyazva maradjanak, ezt az attribútum beállításával interface megadhatja a metadataunnest szinten. A(z) true értékre állítása "kibontja" az összes beágyazott típust (ez a korábbi viselkedés eredménye):

<attr path="/api/package[@name='my.package']/interface[@name='Foo']" name="unnest">true</attr>

Beállítása false esetén a beágyazott típusok a interface alatt maradnak (a .NET működésének megfelelően).

<attr path="/api/package[@name='my.package']/interface[@name='Foo']" name="unnest">false</attr>

Ezzel a módszerrel meghagyhatja a $(AndroidBoundInterfacesContainTypes) tulajdonságot true minden, a jelenleg meglévő beágyazott típussal rendelkező unnest esetén, és beállíthatja a true-t interface-ra. Ezek mindig felső szintű típusok maradnak, míg a később bevezetett új beágyazott típusok beágyazva lesznek.

Statikus és alapértelmezett illesztőtagok (DIM)

A C# hagyományosan nem engedélyezte, hogy a felületek tagokat és static metódusokat tartalmazzanakdefault:

public interface Foo {
  public static void Bar () { ... }
  public default void Baz () { ... }
}

A statikus tagok támogatását a felületeken az biztosítja, hogy áthelyezik őket egy hasonló szerkezetbe class.

public interface IFoo { }

public class Foo
{
    public static void Bar () { ... }
}

default a felületi metódusok hagyományosan nem kötöttek, mivel ezek nem szükségesek, és nem volt C#-szerkezet a támogatásukhoz.

A C# 8 esetén a staticdefault tagok támogatottak a felületeken, tükrözve a Java-felületet:

public interface IFoo
{
    public static void Bar () { ... }
    public default void Baz () { ... }
}

Ez azonban azt jelenti, hogy az class alternatív testvér, amely static tagokat tartalmaz, már nem fog generálódni.

Ha a $AndroidBoundInterfacesContainStaticAndDefaultInterfaceMethods tulajdonságot false értékre állítja a projektfájlban, ezzel visszaállítja az örökölt viselkedést.

Nullaértékű hivatkozási típusok

A null értékű referenciatípusok (NRT) támogatása a Xamarin.Android 11.0-ban lett hozzáadva. Az NRT-támogatás a standard .NET-mechanizmussal engedélyezhető:

<PropertyGroup>
  <Nullable>enable</Nullable>
</PropertyGroup>

Mivel a .NET alapértelmezett értéke, disableugyanez vonatkozik a Xamarin.Android-projektekre is.

Resource.designer.cs

A Xamarin.Android-ban a Java-kötési projektek nem támogatták a Resource.designer.cs fájlok létrehozásának támogatását. Mivel a kötési projektek csak osztálykódtárak a .NET-ben, ez a fájl jön létre. Ez a meglévő projektek migrálása során megszakító változás lehet.

A módosítás egyik hibája például az, ha a kötés létrehoz egy, a gyökérnévtérben elnevezett Resource osztályt:

error CS0101: The namespace 'MyBinding' already contains a definition for 'Resource'

Vagy AndroidX esetén vannak olyan projektfájlok a névvel - , mint például androidx.window/window-extensions.csproj. Ez azt eredményezi, hogy a gyökérnévtér window-extensions, és a C# a következőben érvénytelen: Resource.designer.cs:

error CS0116: A namespace cannot directly contain members such as fields, methods or statements
error CS1514: { expected
error CS1022: Type or namespace definition, or end-of-file expected

A projektfájlban a Resource.designer.cs tulajdonságot állítsa $(AndroidGenerateResourceDesigner)-re a létrehozás letiltásához.

<PropertyGroup>
  <AndroidGenerateResourceDesigner>false</AndroidGenerateResourceDesigner>
</PropertyGroup>