Xamarin.Android 系結專案移轉
在 .NET 中,沒有Android系結專案作為個別專案類型的概念。 任何在 Xamarin.Android 系結項目中運作的 MSBuild 專案群組或建置動作,都支援透過適用於 Android 應用程式或連結庫的 .NET。
若要將 Xamarin.Android 系結連結庫移轉至適用於 Android 的 .NET 類別庫:
在 Visual Studio 中,建立與 Xamarin.Android 系結專案同名的新 Android Java 連結庫系結專案:
開啟項目檔將會確認您有 .NET SDK 樣式專案:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net8.0-android</TargetFramework> <SupportedOSPlatformVersion>21</SupportedOSPlatformVersion> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> </Project>
注意
Android 系結連結庫的項目檔與 Android 類別庫的項目檔相同。
將 Java 封存 (JAR) 或 Android 封存 (AAR) 新增至專案,並確定其建置動作已設定為 AndroidLibrary。
從 Xamarin.Android 系結連結庫複製任何轉換或新增專案。
不支援的舊版選項
不再支援下列舊版選項。 支援的替代方案已提供數年,且最順暢的移轉選項是先使用這些選項來更新及測試您目前的專案,再將其移轉至 .NET。
AndroidClassParser
jar2xml
不再是屬性的有效選項 $(AndroidClassParser)
。 class-parse
現在是預設且唯一支援的選項。
class-parse
會利用中未提供 jar2xml
的許多新式功能,例如:
- 類別方法的自動參數名稱(如果您的 Java 程式代碼是使用
javac -parameters
編譯的 )。 - Kotlin 支援。
- 靜態/預設介面成員 (DIM) 支援。
- Java 可為 Null 的參考類型 (NRT) 註釋支援。
AndroidCodegenTarget
XamarinAndroid
不再是屬性的有效選項 $(AndroidCodegenTarget)
。 XAJavaInterop1
現在是預設且唯一支援的選項。
如果您的檔案中有 Additions
與所產生系結程式代碼互動的手動系結程序代碼,可能需要更新它才能與 XAJavaInterop1
相容。
默認檔案包含
指定下列檔案結構:
Transforms/
Metadata.xml
foo.jar
Transforms\*.xml
檔案會自動包含為@(TransformFile)
專案,且.aar
.jar
/檔案會自動包含為@(AndroidLibrary)
專案。 這會使用 元數據修正從 Transforms\Metadata.xml
中foo.jar
找到的Java型別系結 C# 類型。
默認Android相關檔案擷取行為定義於 AutoImport.props 中。 您可以將 屬性設定$(EnableDefaultAndroidItems)
為 來停用 Android 項目的行為,或將 屬性false
設定$(EnableDefaultItems)
為 false
來停用所有預設專案包含行為。
不想要 .jar
或 .aar
檔案可以包含在預設通配符中。 例如,下列 C# 編譯程序錯誤會導致 AndroidStudio\gradle\wrapper\gradle-wrapper.jar
檔案意外系結:
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)'
若要解決此問題,您可以移除項目檔中的特定檔案:
<ItemGroup>
<AndroidLibrary Remove="AndroidStudio\gradle\wrapper\gradle-wrapper.jar" />
</ItemGroup>
或者,您可以排除資料夾中的所有檔案:
<AndroidLibrary Remove="AndroidStudio\**\*" />
新專案組名
<AndroidLibrary>
現在是用於所有 .jar
和 .aar
檔案的建議專案群組。 在 Xamarin.Android 中,使用了下列專案群組,可改為使用專案元數據來達到相同的結果:
舊版專案群組 | 新增專案群組 | 項目中繼資料 | 舊版項目類型 |
---|---|---|---|
AndroidAarLibrary |
AndroidLibrary |
Bind="false" |
申請 |
AndroidJavaLibrary |
AndroidLibrary |
Bind="false" |
應用程式或類別庫 |
EmbeddedJar |
AndroidLibrary |
n/a | 系結專案 |
EmbeddedReferenceJar |
AndroidLibrary |
Bind="false" |
系結專案 |
InputJar |
AndroidLibrary |
Pack="false" |
系結專案 |
LibraryProjectZip |
AndroidLibrary |
n/a | 系結專案 |
.aar
請考慮 或 .jar
檔案,而您對此不感興趣,包括 C# 系結。 當您有不需要從 C# 呼叫的 Java 或 Kotlin 相依性時,這種情況很常見。 在這裡設定,您可以將中繼資料設定 Bind
為 false
。 根據預設,檔案會依預設通配符挑選。 您也可以使用 Update
屬性來設定 Bind
元資料:
<ItemGroup>
<AndroidLibrary Update="foo.jar" Bind="false">
</ItemGroup>
在 Android 類別庫專案中,這會依目前的方式轉散發 .jar
產生的 NuGet 套件內的檔案。 在Android應用程式專案中,這會在 .jar
產生的 .apk
或 .aab
檔案中包含檔案。 這兩者都不會包含此 Java 連結庫的 C# 系結。
內嵌 JAR/AAR 檔案
在 Xamarin.Android 中,Java .jar
或 .aar
通常內嵌到系結 .dll
中做為內嵌資源。 不過,這會導致組建變慢,因為 .dll
每個組建都必須開啟並掃描Java程式碼。 如果找到,則必須將它擷取到要使用的磁碟。
在 .NET 中,Java 程式代碼不再內嵌在 中 .dll
。 應用程式建置程式會自動將它找到的任何 .jar
或 .aar
檔案包含在與參考 .dll
相同的目錄中。
如果專案透過 <PackageReference>
或 <ProjectReference>
參考系結,則所有專案都有效,而且不需要其他考慮。 不過,如果專案透過 <Reference>
/.aar
.jar
參考系結,則必須位於 旁邊的 。.dll
也就是說,針對下列參考:
<Reference Include="MyBinding.dll" />
如下列範例中的目錄將無法運作:
lib/
MyBinding.dll
相反地,目錄也必須包含機器碼:
lib/
MyBinding.dll
mybinding.jar
移轉考量
默認會設定數個新功能,以協助產生更符合其 Java 對應項的系結。 不過,如果您要移轉現有的系結專案,這些功能可能會建立與現有系結不相容的 API 系結。 若要維護相容性,您可能想要停用或修改這些新功能。
介面常數
傳統上,C# 不允許在 中 interface
宣告常數,這是 Java 中的常見模式:
public interface Foo {
public static int BAR = 1;
}
建立包含常數的替代 class
專案,先前支援此模式:
public abstract class Foo : Java.Lang.Object
{
public static int Bar = 1;
}
使用 C# 8 時,這些常數會放在 上 interface
:
public interface IFoo
{
public static int Bar = 1;
}
不過,這表示不再產生現有程序代碼可能相依的替代類別。
將 $(AndroidBoundInterfacesContainConstants)
項目檔中的 屬性 false
設定為 會還原為舊版行為。
巢狀介面類型
傳統上,C# 不允許在 interface
Java 中宣告巢狀類型:
public interface Foo {
public class Bar { }
}
使用由介面和巢狀類型名稱所組成的產生名稱,將巢狀類型移至最上層類型,支援此模式:
public interface IFoo { }
public class IFooBar : Java.Lang.Object { }
使用 C# 8 時,巢狀類型可以放在 中 interface
:
public interface IFoo
{
public class Bar : Java.Lang.Object { }
}
不過,這表示不再產生現有程序代碼可能相依的最上層類別。
將 $(AndroidBoundInterfacesContainTypes)
項目檔中的 屬性 false
設定為 會還原為舊版行為。
例如,如果您想要使用混合式方法,讓現有的巢狀類型保持移至最上層類型,但允許任何未來的巢狀類型維持巢狀狀態,您可以在層級使用 metadata
來設定 屬性來unnest
指定這個interface
值。 將它設定為 true
會導致任何巢狀類型「取消巢狀」(舊版行為):
<attr path="/api/package[@name='my.package']/interface[@name='Foo']" name="unnest">true</attr>
將它設定為 false
會導致巢狀類型留在 巢狀結構中 interface
(.NET 行為):
<attr path="/api/package[@name='my.package']/interface[@name='Foo']" name="unnest">false</attr>
使用此方法時,您可以將 屬性保留$(AndroidBoundInterfacesContainTypes)
為 true
,並針對unnest
您目前擁有的巢狀類型設定interface
為 true
。 這些類型一律會維持最上層類型,而稍後引進的任何新巢狀類型都會巢狀化。
靜態和預設介面成員 (DIM)
傳統上,C# 不允許介面包含 static
成員和 default
方法:
public interface Foo {
public static void Bar () { ... }
public default void Baz () { ... }
}
已支援介面上的靜態成員,方法是將它們移至同層級 class
:
public interface IFoo { }
public class Foo
{
public static void Bar () { ... }
}
default
介面方法傳統上未系結,因為它們並非必要,而且沒有 C# 建構可支持它們。
使用 C# 8, static
且 default
介面上支持成員,鏡像 Java 介面:
public interface IFoo
{
public static void Bar () { ... }
public default void Baz () { ... }
}
不過,這表示將不再產生包含static
成員的替代同層級class
。
將 $AndroidBoundInterfacesContainStaticAndDefaultInterfaceMethods
項目檔中的 屬性 false
設定為 會還原為舊版行為。
可為 Null 的參考型別
在 Xamarin.Android 11.0 中新增了可為 Null 的參考型別 (NRT) 支援。 您可以使用標準 .NET 機制來啟用 NRT 支援:
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
因為 .NET 的預設值是 disable
,因此同樣適用於 Xamarin.Android 專案。
Resource.designer.cs
在 Xamarin.Android 中,Java 系結專案不支援產生 Resource.designer.cs
檔案。 由於系結專案只是 .NET 中的類別庫,因此會產生此檔案。 移轉現有專案時,這可能是重大變更。
此變更失敗的其中一個範例是,如果您的系結在根命名空間中產生名為 Resource
的類別:
error CS0101: The namespace 'MyBinding' already contains a definition for 'Resource'
或者,在 AndroidX 的情況下,名稱中有項目檔 -
,例如 androidx.window/window-extensions.csproj
。 這會導致 根命名空間 window-extensions
和 中的 Resource.designer.cs
C# 無效:
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
若要停用 Resource.designer.cs
產生,請將 $(AndroidGenerateResourceDesigner)
項目檔中的 屬性設定為 false
:
<PropertyGroup>
<AndroidGenerateResourceDesigner>false</AndroidGenerateResourceDesigner>
</PropertyGroup>