Migracja projektu powiązania platformy Xamarin.Android
Na platformie .NET nie ma pojęcia projektu powiązania systemu Android jako oddzielnego typu projektu. Wszystkie grupy elementów programu MSBuild lub akcje kompilacji, które działają w projektach powiązań platformy Xamarin.Android, są obsługiwane za pośrednictwem aplikacji lub biblioteki platformy .NET dla systemu Android.
Aby przeprowadzić migrację biblioteki powiązań platformy Xamarin.Android do biblioteki klas platformy .NET dla systemu Android:
W programie Visual Studio utwórz nowy projekt powiązania biblioteki Java systemu Android o takiej samej nazwie jak projekt powiązania platformy Xamarin.Android:
Otwarcie pliku projektu potwierdzi, że masz projekt w stylu zestawu SDK platformy .NET:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net8.0-android</TargetFramework> <SupportedOSPlatformVersion>21</SupportedOSPlatformVersion> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> </Project>
Uwaga
Plik projektu dla biblioteki powiązań systemu Android jest identyczny z plikiem projektu dla biblioteki klas systemu Android.
Dodaj archiwum Java (JAR) lub Archiwum systemu Android (AAR) do projektu i upewnij się, że jego akcja kompilacji jest ustawiona na AndroidLibrary.
Skopiuj wszelkie przekształcenia lub dodatki z biblioteki powiązań platformy Xamarin.Android.
Nieobsługiwane opcje starszej wersji
Następujące starsze opcje nie są już obsługiwane. Obsługiwane alternatywy są dostępne od kilku lat, a najbardziej płynną opcją migracji jest zaktualizowanie i przetestowanie bieżących projektów przy użyciu tych opcji przed migracją ich do platformy .NET.
AndroidClassParser
jar2xml
nie jest już prawidłową opcją $(AndroidClassParser)
dla właściwości . class-parse
jest teraz opcją domyślną i obsługiwaną tylko.
class-parse
korzysta z wielu nowych nowoczesnych funkcji, które nie są dostępne w systemie jar2xml
, takich jak:
- Automatyczne nazwy parametrów dla metod klas (jeśli kod Java jest kompilowany za pomocą polecenia
javac -parameters
). - Obsługa Kotlin.
- Obsługa elementu członkowskiego interfejsu statycznego/domyślnego (DIM).
- Obsługa adnotacji typu odwołania o wartości null języka Java (NRT).
AndroidCodegenTarget
XamarinAndroid
nie jest już prawidłową opcją $(AndroidCodegenTarget)
dla właściwości . XAJavaInterop1
jest teraz opcją domyślną i obsługiwaną tylko.
Jeśli masz ręcznie powiązany kod w Additions
plikach, który współdziała z wygenerowanym kodem powiązania, może być konieczne zaktualizowanie go tak, aby był zgodny z elementem XAJavaInterop1
.
Domyślne dołączanie plików
Biorąc pod uwagę następującą strukturę plików:
Transforms/
Metadata.xml
foo.jar
Transforms\*.xml
pliki są automatycznie dołączane jako @(TransformFile)
element, a .jar
/.aar
pliki są automatycznie dołączane jako @(AndroidLibrary)
element. Spowoduje to powiązanie typów języka C# dla typów języka Java znalezionych przy foo.jar
użyciu poprawek metadanych z witryny Transforms\Metadata.xml
.
Domyślne zachowanie tworzenia globbingu pliku powiązanego z systemem Android jest definiowane w pliku AutoImport.props. To zachowanie można wyłączyć dla elementów systemu Android, ustawiając $(EnableDefaultAndroidItems)
właściwość na false
, lub wszystkie domyślne zachowanie dołączania elementów można wyłączyć, ustawiając $(EnableDefaultItems)
właściwość na false
.
.jar
Niepożądane lub .aar
pliki mogą być dołączone do domyślnych symboli wieloznacznych. Na przykład następujące błędy kompilatora języka C# wynikają z AndroidStudio\gradle\wrapper\gradle-wrapper.jar
niezamierzonego powiązania pliku:
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)'
Aby rozwiązać ten problem, możesz usunąć określony plik w pliku projektu:
<ItemGroup>
<AndroidLibrary Remove="AndroidStudio\gradle\wrapper\gradle-wrapper.jar" />
</ItemGroup>
Alternatywnie można wykluczyć wszystkie pliki w folderze:
<AndroidLibrary Remove="AndroidStudio\**\*" />
Nazwy nowych grup elementów
<AndroidLibrary>
jest teraz zalecaną grupą elementów do użycia dla wszystkich .jar
plików i .aar
. W środowisku Xamarin.Android użyto następujących grup elementów, które mogą zamiast tego użyć metadanych elementu, aby uzyskać ten sam wynik:
Starsza grupa elementów | Nowa grupa elementów | Metadane elementu | Starszy typ projektu |
---|---|---|---|
AndroidAarLibrary |
AndroidLibrary |
Bind="false" |
Aplikacja |
AndroidJavaLibrary |
AndroidLibrary |
Bind="false" |
Biblioteka aplikacji lub klas |
EmbeddedJar |
AndroidLibrary |
nie dotyczy | Wiązanie projektu |
EmbeddedReferenceJar |
AndroidLibrary |
Bind="false" |
Wiązanie projektu |
InputJar |
AndroidLibrary |
Pack="false" |
Wiązanie projektu |
LibraryProjectZip |
AndroidLibrary |
nie dotyczy | Wiązanie projektu |
Rozważ plik .aar
lub .jar
, w którym nie interesuje Cię dołączenie powiązania w języku C#. Jest to typowe w przypadku, gdy masz zależności języka Java lub Kotlin, których nie trzeba wywoływać z języka C#. W takim przypadku można ustawić Bind
metadane na false
wartość . Domyślnie plik jest pobierany do domyślnych symboli wieloznacznych. Możesz również użyć atrybutu Update
Bind
, aby ustawić metadane:
<ItemGroup>
<AndroidLibrary Update="foo.jar" Bind="false">
</ItemGroup>
W projekcie biblioteki klas systemu Android będzie to redystrybuować .jar
plik wewnątrz wynikowego pakietu NuGet, tak jak to jest. W projekcie aplikacji systemu Android będzie to zawierać .jar
plik w wynikowym .apk
pliku lub .aab
pliku. Żadna z nich nie zawiera powiązania języka C# dla tej biblioteki Języka Java.
Osadzone pliki JAR/AAR
W środowisku Xamarin.Android środowisko Java .jar
lub .aar
często było osadzone w powiązaniu .dll
jako zasób osadzony. Doprowadziło to jednak do spowolnienia kompilacji, ponieważ każdy z nich .dll
musi być otwarty i zeskanowany pod kątem kodu Java. W przypadku znalezienia należy wyodrębnić go do dysku, aby można go było użyć.
Na platformie .NET kod Języka Java nie jest już osadzony w elemecie .dll
. Proces kompilacji aplikacji będzie automatycznie uwzględniać wszystkie .jar
znalezione pliki lub .aar
w tym samym katalogu co przywoływny .dll
plik .
Jeśli projekt odwołuje się do powiązania za pośrednictwem metody <PackageReference>
lub <ProjectReference>
wszystko działa i nie są wymagane żadne dodatkowe zagadnienia. Jeśli jednak projekt odwołuje się do powiązania za pomocą metody <Reference>
, .jar
/.aar
element musi znajdować się obok elementu ..dll
Oznacza to, że w przypadku następującego odwołania:
<Reference Include="MyBinding.dll" />
Katalog podobny do tego w poniższym przykładzie nie będzie działać:
lib/
MyBinding.dll
Zamiast tego katalog musi również zawierać kod natywny:
lib/
MyBinding.dll
mybinding.jar
Zagadnienia dotyczące migracji
Istnieje kilka nowych funkcji ustawionych domyślnie, aby ułatwić tworzenie powiązań, które lepiej pasują do ich odpowiedników w języku Java. Jednak w przypadku migrowania istniejącego projektu powiązania te funkcje mogą tworzyć powiązania, które nie są zgodne z istniejącymi powiązaniami interfejsu API. Aby zachować zgodność, możesz wyłączyć lub zmodyfikować te nowe funkcje.
Stałe interfejsu
Tradycyjnie język C# nie zezwalał na deklarowanie stałych w obiekcie , który jest typowym wzorcem interface
w języku Java:
public interface Foo {
public static int BAR = 1;
}
Ten wzorzec był wcześniej obsługiwany przez utworzenie alternatywy class
zawierającej stałe:
public abstract class Foo : Java.Lang.Object
{
public static int Bar = 1;
}
W języku C# 8 te stałe są umieszczane w obiekcie interface
:
public interface IFoo
{
public static int Bar = 1;
}
Oznacza to jednak, że klasa alternatywna, od którego może zależeć istniejący kod, nie jest już generowana.
$(AndroidBoundInterfacesContainConstants)
Ustawienie właściwości na false
wartość w pliku projektu spowoduje przywrócenie starszego zachowania.
Typy zagnieżdżonych interfejsów
Tradycyjnie język C# nie zezwalał na deklarowanie typów zagnieżdżonych w obiekcie , który jest dozwolony w interface
języku Java:
public interface Foo {
public class Bar { }
}
Ten wzorzec był obsługiwany przez przeniesienie typu zagnieżdżonego do typu najwyższego poziomu o wygenerowanej nazwie składającej się z interfejsu i nazwy typu zagnieżdżonego:
public interface IFoo { }
public class IFooBar : Java.Lang.Object { }
W języku C# 8 zagnieżdżone typy można umieścić w pliku interface
:
public interface IFoo
{
public class Bar : Java.Lang.Object { }
}
Oznacza to jednak, że klasa najwyższego poziomu, od którego może zależeć istniejący kod, nie jest już generowana.
$(AndroidBoundInterfacesContainTypes)
Ustawienie właściwości na false
wartość w pliku projektu spowoduje przywrócenie starszego zachowania.
Jeśli na przykład chcesz użyć podejścia hybrydowego, aby zachować istniejące zagnieżdżone typy przeniesione do typu najwyższego poziomu, ale zezwolić na pozostanie zagnieżdżonych typów w przyszłości, możesz określić je na interface
poziomie , używając metadata
polecenia , aby ustawić unnest
atrybut. Ustawienie tej true
wartości spowoduje "anulowanie zagnieżdżania" wszystkich typów zagnieżdżonych (zachowanie starszej wersji):
<attr path="/api/package[@name='my.package']/interface[@name='Foo']" name="unnest">true</attr>
Ustawienie tej false
wartości spowoduje zagnieżdżenia typów pozostałych zagnieżdżonych w zachowaniu (zachowanie platformy interface
.NET):
<attr path="/api/package[@name='my.package']/interface[@name='Foo']" name="unnest">false</attr>
Korzystając z tego podejścia, można pozostawić $(AndroidBoundInterfacesContainTypes)
właściwość jako true
i ustawioną unnest
na true
dla każdego interface
z aktualnie zagnieżdżonych typów. Będą one zawsze pozostawać typami najwyższego poziomu, podczas gdy wszystkie nowe typy zagnieżdżone wprowadzone później zostaną zagnieżdżone.
Statyczne i domyślne elementy członkowskie interfejsu (DIM)
Tradycyjnie język C# nie zezwala na interfejsy zawierające static
elementy członkowskie i default
metody:
public interface Foo {
public static void Bar () { ... }
public default void Baz () { ... }
}
Statyczne elementy członkowskie w interfejsach zostały obsługiwane przez przeniesienie ich do elementu równorzędnego class
:
public interface IFoo { }
public class Foo
{
public static void Bar () { ... }
}
default
Metody interfejsu tradycyjnie nie były powiązane, ponieważ nie są wymagane i nie było konstrukcji języka C#, aby je obsługiwać.
W języku C# 8 static
i default
elementy członkowskie są obsługiwane w interfejsach, dublując interfejs Java:
public interface IFoo
{
public static void Bar () { ... }
public default void Baz () { ... }
}
Oznacza to jednak, że alternatywne elementy równorzędne class
static
zawierające elementy członkowskie nie będą już generowane.
$AndroidBoundInterfacesContainStaticAndDefaultInterfaceMethods
Ustawienie właściwości na false
wartość w pliku projektu spowoduje przywrócenie starszego zachowania.
Typy referencyjne dopuszczające wartość null
Dodano obsługę typów odwołań dopuszczanych do wartości null (NRT) na platformie Xamarin.Android 11.0. Obsługę nrT można włączyć przy użyciu standardowego mechanizmu .NET:
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
Ponieważ ustawieniem domyślnym dla platformy .NET jest disable
, dotyczy to również projektów platformy Xamarin.Android.
Resource.designer.cs
W środowisku Xamarin.Android projekty powiązań Języka Java nie obsługiwały generowania Resource.designer.cs
pliku. Ponieważ projekty powiązań to tylko biblioteki klas na platformie .NET, ten plik zostanie wygenerowany. Może to być zmiana powodująca niezgodność podczas migrowania istniejących projektów.
Przykładem niepowodzenia tej zmiany jest wygenerowanie klasy o nazwie Resource
w głównej przestrzeni nazw:
error CS0101: The namespace 'MyBinding' already contains a definition for 'Resource'
Lub w przypadku systemu AndroidX istnieją pliki projektu z -
nazwą, taką jak androidx.window/window-extensions.csproj
. Powoduje to, że główna przestrzeń nazw window-extensions
i nieprawidłowy język C# w pliku 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
Aby wyłączyć Resource.designer.cs
generowanie $(AndroidGenerateResourceDesigner)
, ustaw właściwość na false
w pliku projektu:
<PropertyGroup>
<AndroidGenerateResourceDesigner>false</AndroidGenerateResourceDesigner>
</PropertyGroup>