Bagikan melalui


Migrasi proyek pengikatan Xamarin.Android

Di .NET, tidak ada konsep proyek pengikatan Android sebagai jenis proyek terpisah. Salah satu grup item MSBuild atau tindakan build yang berfungsi di proyek pengikatan Xamarin.Android didukung melalui aplikasi atau pustaka .NET untuk Android.

Untuk memigrasikan pustaka pengikatan Xamarin.Android ke pustaka kelas .NET untuk Android:

  1. Di Visual Studio, buat proyek Pengikatan Pustaka Java Android baru dengan nama yang sama dengan proyek pengikatan Xamarin.Android Anda:

    Cuplikan layar membuat proyek Pengikatan Pustaka Android Java di Visual Studio.

    Membuka file proyek akan mengonfirmasi bahwa Anda memiliki proyek gaya .NET SDK:

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

    Catatan

    File proyek untuk pustaka pengikatan Android identik dengan file proyek untuk pustaka kelas Android.

  2. Tambahkan Java Archive (JAR) atau Android Archive (AAR) Anda ke proyek dan pastikan bahwa tindakan buildnya diatur ke AndroidLibrary.

  3. Salin transformasi atau penambahan apa pun dari pustaka pengikatan Xamarin.Android Anda.

Opsi warisan yang tidak didukung

Opsi warisan berikut tidak lagi didukung. Alternatif yang didukung telah tersedia selama beberapa tahun, dan opsi migrasi termulus adalah memperbarui dan menguji proyek Anda saat ini dengan opsi ini sebelum memigrasikannya ke .NET.

AndroidClassParser

jar2xml bukan lagi opsi yang valid untuk $(AndroidClassParser) properti . class-parse sekarang menjadi opsi default dan hanya didukung.

class-parse memanfaatkan banyak fitur modern baru yang tidak tersedia di jar2xml, seperti:

  • Nama parameter otomatis untuk metode kelas (jika kode Java Anda dikompilasi dengan javac -parameters).
  • Dukungan Kotlin.
  • Dukungan anggota antarmuka statis/default (DIM).
  • Dukungan anotasi jenis referensi Java Nullable (NRT).

AndroidCodegenTarget

XamarinAndroid bukan lagi opsi yang valid untuk $(AndroidCodegenTarget) properti . XAJavaInterop1 sekarang menjadi opsi default dan hanya didukung.

Jika Anda memiliki kode terikat tangan dalam file Anda Additions yang berinteraksi dengan kode pengikatan yang dihasilkan, mungkin perlu diperbarui agar kompatibel dengan XAJavaInterop1.

Penyertaan file default

Mengingat struktur file berikut:

Transforms/
    Metadata.xml
foo.jar

Transforms\*.xmlfile secara otomatis disertakan sebagai @(TransformFile) item, dan.aar.jar/file secara otomatis disertakan sebagai @(AndroidLibrary) item. Ini akan mengikat jenis C# untuk jenis Java yang ditemukan dalam foo.jar menggunakan perbaikan metadata dari Transforms\Metadata.xml.

Perilaku globbing file terkait Android default didefinisikan dalam AutoImport.props. Perilaku ini dapat dinonaktifkan untuk item Android dengan mengatur $(EnableDefaultAndroidItems) properti ke false, atau semua perilaku penyertaan item default dapat dinonaktifkan dengan mengatur $(EnableDefaultItems) properti ke false.

Tidak diinginkan .jar atau .aar file dapat disertakan dengan kartubebas default. Misalnya, kesalahan pengkompilasi C# berikut menghasilkan file yang AndroidStudio\gradle\wrapper\gradle-wrapper.jar tidak disengaja terikat:

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)'

Untuk mengatasi masalah ini, Anda dapat menghapus file tertentu dalam file proyek Anda:

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

Atau, Anda dapat mengecualikan semua file dalam folder:

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

Nama grup item baru

<AndroidLibrary> sekarang adalah grup item yang direkomendasikan untuk digunakan untuk semua .jar file dan .aar . Di Xamarin.Android, grup item berikut digunakan, yang dapat menggunakan metadata item untuk mencapai hasil yang sama:

Grup Item Warisan Grup Item Baru Item Metadata Jenis Proyek Warisan
AndroidAarLibrary AndroidLibrary Bind="false" Aplikasi
AndroidJavaLibrary AndroidLibrary Bind="false" Pustaka aplikasi atau kelas
EmbeddedJar AndroidLibrary n/a Proyek pengikatan
EmbeddedReferenceJar AndroidLibrary Bind="false" Proyek pengikatan
InputJar AndroidLibrary Pack="false" Proyek pengikatan
LibraryProjectZip AndroidLibrary n/a Proyek pengikatan

Pertimbangkan file .aar atau .jar , di mana Anda tidak tertarik untuk menyertakan pengikatan C#. Ini umum untuk kasus di mana Anda memiliki dependensi Java atau Kotlin yang tidak perlu Anda panggil dari C#. Dalam hal ini, Anda dapat mengatur Bind metadata ke false. Secara default, file diambil oleh wildcard default. Anda juga dapat menggunakan Update atribut untuk mengatur Bind metadata:

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

Dalam proyek pustaka kelas Android, ini akan mendistribusikan .jar ulang file di dalam paket NuGet yang dihasilkan apa adanya. Dalam proyek aplikasi Android, ini akan menyertakan .jar file dalam .apk hasil atau .aab file. Keduanya tidak akan menyertakan pengikatan C# untuk pustaka Java ini.

File JAR/AAR yang disematkan

Di Xamarin.Android, Java .jar atau .aar sering disematkan ke dalam pengikatan .dll sebagai Sumber Daya Tersemat. Namun, ini menyebabkan build lambat, karena masing-masing .dll harus dibuka dan dipindai untuk kode Java. Jika ditemukan, disk harus diekstrak ke disk yang akan digunakan.

Di .NET, kode Java tidak lagi disematkan di .dll. Proses build aplikasi akan secara otomatis menyertakan file atau .aar apa pun .jar yang ditemukannya di direktori yang sama dengan yang direferensikan .dll.

Jika proyek mereferensikan pengikatan melalui <PackageReference> atau <ProjectReference> kemudian semuanya berfungsi dan tidak ada pertimbangan tambahan yang diperlukan. Namun, jika proyek mereferensikan pengikatan melalui <Reference>,.aar.jar/harus terletak di .dllsamping . Artinya, untuk referensi berikut:

<Reference Include="MyBinding.dll" />

Direktori seperti yang ada dalam contoh berikut tidak akan berfungsi:

lib/
    MyBinding.dll

Sebagai gantinya, direktori juga harus berisi kode asli:

lib/
    MyBinding.dll
    mybinding.jar

Pertimbangan migrasi

Ada beberapa fitur baru yang ditetapkan secara default untuk membantu menghasilkan pengikatan yang lebih cocok dengan rekan-rekan Java mereka. Namun, jika Anda memigrasikan proyek pengikatan yang ada, fitur-fitur ini dapat membuat pengikatan yang tidak kompatibel dengan pengikatan yang ada. Untuk mempertahankan kompatibilitas, Anda mungkin ingin menonaktifkan atau mengubah fitur baru ini.

Konstanta antarmuka

Secara tradisional, C# belum mengizinkan konstanta untuk dideklarasikan dalam interface, yang merupakan pola umum di Java:

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

Pola ini sebelumnya didukung dengan membuat alternatif class yang berisi konstanta:

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

Dengan C# 8, konstanta ini ditempatkan pada interface:

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

Namun, ini berarti bahwa kelas alternatif yang mungkin bergantung pada kode yang ada tidak lagi dihasilkan.

Mengatur properti ke $(AndroidBoundInterfacesContainConstants)false dalam file proyek Anda akan kembali ke perilaku warisan.

Jenis antarmuka berlapis

Secara tradisional, C# belum mengizinkan jenis berlapis untuk dideklarasikan dalam interface, yang diizinkan di Java:

public interface Foo {
     public class Bar { }
}

Pola ini didukung dengan memindahkan jenis berlapis ke jenis tingkat atas dengan nama yang dihasilkan yang terdiri dari antarmuka dan nama jenis berlapis:

public interface IFoo { }

public class IFooBar : Java.Lang.Object { }

Dengan C# 8, jenis berlapis dapat ditempatkan di interface:

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

Namun, ini berarti bahwa kelas tingkat atas yang mungkin bergantung pada kode yang ada tidak lagi dihasilkan.

Mengatur properti ke $(AndroidBoundInterfacesContainTypes)false dalam file proyek Anda akan kembali ke perilaku warisan.

Jika Anda ingin menggunakan pendekatan hibrid, misalnya, untuk menjaga jenis berlapis yang ada dipindahkan ke jenis tingkat atas, tetapi memungkinkan jenis berlapis di masa mendatang tetap berlapis, Anda dapat menentukan ini pada interface tingkat menggunakan metadata untuk mengatur unnest atribut. Mengaturnya ke true akan mengakibatkan "tidak bersarang" jenis berlapis apa pun (perilaku warisan):

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

Mengaturnya ke false akan mengakibatkan jenis berlapis yang tersisa di interface dalam (perilaku.NET):

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

Dengan menggunakan pendekatan ini, Anda dapat meninggalkan $(AndroidBoundInterfacesContainTypes) properti sebagai true dan mengatur unnest ke true untuk setiap interface dengan jenis berlapis yang saat ini Anda miliki. Ini akan selalu tetap menjadi jenis tingkat atas, sementara jenis berlapis baru yang diperkenalkan nanti akan ditumpuk.

Anggota antarmuka statis dan default (DIM)

Secara tradisional, C# belum mengizinkan antarmuka untuk berisi static anggota dan default metode:

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

Anggota statis pada antarmuka telah didukung dengan memindahkannya ke saudara kandung class:

public interface IFoo { }

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

default metode antarmuka secara tradisional belum terikat, karena tidak diperlukan dan tidak ada konstruksi C# untuk mendukungnya.

Dengan C# 8, static dan default anggota didukung pada antarmuka, mencerminkan antarmuka Java:

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

Namun, ini berarti saudara kandung class alternatif yang berisi static anggota tidak akan lagi dihasilkan.

Mengatur properti ke $AndroidBoundInterfacesContainStaticAndDefaultInterfaceMethodsfalse dalam file proyek Anda akan kembali ke perilaku warisan.

Jenis referensi yang dapat diubah ke null

Dukungan untuk Jenis Referensi Nullable (NRT) ditambahkan di Xamarin.Android 11.0. Dukungan NRT dapat diaktifkan menggunakan mekanisme .NET standar:

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

Karena default untuk .NET adalah disable, hal yang sama berlaku untuk proyek Xamarin.Android.

Resource.designer.cs

Di Xamarin.Android, proyek pengikatan Java tidak mendukung pembuatan Resource.designer.cs file. Karena proyek pengikatan hanyalah pustaka kelas di .NET, file ini akan dibuat. Ini bisa menjadi perubahan yang melanggar saat memigrasikan proyek yang ada.

Salah satu contoh kegagalan dari perubahan ini, adalah jika pengikatan Anda menghasilkan kelas bernama Resource di namespace layanan akar:

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

Atau dalam kasus AndroidX, ada file proyek dengan - dalam nama seperti androidx.window/window-extensions.csproj. Ini menghasilkan namespace window-extensions layanan akar dan C# yang tidak valid di 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

Untuk menonaktifkan Resource.designer.cs pembuatan, atur properti ke false$(AndroidGenerateResourceDesigner) dalam file proyek Anda:

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