在 .NET 中,沒有Android系結專案作為個別專案類型的概念。 任何在 Xamarin.Android 綁定專案中運作的 MSBuild 項目群組或建置動作,都支援透過 .NET 適用於 Android 應用程式或庫。
若要將 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的元數據修正將C#類型系結到foo.jar中找到的Java型別。
預設的 Android 相關檔案匹配行為定義於 AutoImport.props 中。 您可以透過將 $(EnableDefaultAndroidItems) 屬性設定為 false,來停用 Android 項目的此行為,或透過將 $(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> 參考系結,則 .jar/.aar 必須位於 .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;
}
通過建立包含常數的替代版本,此模式先前得到支援:
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,將使行為還原為舊版模式。
例如,如果您想要使用混合式方法,將現有的巢狀類型移到最上層類型,但允許未來的巢狀類型保持巢狀狀態,您可以在 interface 層級使用 metadata,並設定 unnest 屬性來指定這一點。 將其設定為 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,並針對您目前擁有的巢狀類型的每個interface,將unnest設定為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,可還原至舊版行為。
可為空的參考類型
在 Xamarin.Android 11.0 中新增了 Nullable Reference Types (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>