Xamarin.Android バインディング プロジェクトの移行
.NET には、別個のプロジェクト タイプとしての Android バインディング プロジェクトの概念はありません。 Xamarin.Android バインディング プロジェクトで動作する MSBuild 項目グループまたはビルド アクションは、.NET for Android アプリまたはライブラリを通じてサポートされます。
Xamarin.Android バインディング ライブラリを .NET for Android クラス ライブラリに移行するには、次の手順を行います。
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>
Note
Android バインディング ライブラリのプロジェクト ファイルは、Android クラス ライブラリのプロジェクト ファイルと同じです。
Java Archive (JAR) または Android Archive (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)
項目として自動的に組み込まれ、.jar
/.aar
ファイルは @(AndroidLibrary)
項目として自動的に組み込まれます。 この結果、Transforms\Metadata.xml
からのメタデータ修正を使用して、foo.jar
で見つかった Java 型に C# 型がバインドされます。
既定の 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 |
該当なし | プロジェクトをバインドする |
EmbeddedReferenceJar |
AndroidLibrary |
Bind="false" |
プロジェクトをバインドする |
InputJar |
AndroidLibrary |
Pack="false" |
プロジェクトをバインドする |
LibraryProjectZip |
AndroidLibrary |
該当なし | プロジェクトをバインドする |
C# バインディングを含めるのに関心がない .aar
ファイルまたは .jar
ファイルを検討してください。 これは、C# から呼び出す必要のない Java または Kotlin の依存関係がある場合に一般的です。 この場合、Bind
のメタデータを false
に設定できます。 既定では、ファイルは既定のワイルドカードによって取得されます。 Update
属性を使用して Bind
メタデータを設定することもできます。
<ItemGroup>
<AndroidLibrary Update="foo.jar" Bind="false">
</ItemGroup>
Android クラス ライブラリ プロジェクトでは、結果の NuGet パッケージ内の .jar
ファイルがそのまま再配布されます。 Android アプリケーション プロジェクトでは、結果の .apk
ファイルまたは .aab
ファイルに .jar
ファイルが含まれます。 この Java ライブラリの C# バインドも含まれていません。
埋め込み JAR/AAR ファイル
Xamarin.Android では、Java の .jar
または .aar
が、頻繫に埋め込みリソースとしてバインディング .dll
に埋め込まれることがありました。 ただし、各 .dll
を開いて Java コードをスキャンする必要があるため、ビルドが遅くなります。 見つかった場合は、使用するディスクに抽出する必要があります。
.NET では、Java コードは .dll
に埋め込まれなくなりました。 アプリのビルド プロセスでは、参照される .dll
と同じディレクトリ内で見つかった .jar
ファイルまたは .aar
ファイルが自動的に組み込まれます。
プロジェクトが <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;
}
このパターンは、以前は定数を含む代替の 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
を使用して interface
レベルでこれを指定し、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
に設定すると、従来の動作に戻ります。
null 許容参照型
Xamarin.Android 11.0 に Null 許容参照型 (NRT) のサポートが追加されました。 NRT のサポートは、標準の .NET メカニズムを使用して有効にできます。
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
.NET の既定値は disable
なので、同じことが Xamarin.Android プロジェクトにも当てはまります。
Resource.designer.cs
Xamarin.Android の Java バインド プロジェクトでは、Resource.designer.cs
ファイルの生成をサポートしていませんでした。 .NET では、バインド プロジェクトはクラス ライブラリに過ぎないため、このファイルが生成されます。 既存のプロジェクトを移行する場合、これは破壊的変更になる可能性があります。
この変更によるエラーの 1 つの例は、バインドによってルート名前空間に 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>
.NET MAUI