次の方法で共有


Xamarin.Android バインド プロジェクトの移行

.NET では、別のプロジェクトの種類として Android バインド プロジェクトの概念はありません。 Xamarin.Android バインド プロジェクトで動作する MSBuild 項目グループまたはビルド アクションは、.NET for Android アプリまたはライブラリを通じてサポートされます。

Xamarin.Android バインド ライブラリを .NET for Android クラス ライブラリに移行するには:

  1. Visual Studio で、Xamarin.Android バインド プロジェクトと同じ名前の新しい Android Java ライブラリ バインド プロジェクトを作成します。

    Visual Studio で 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 クラス ライブラリのプロジェクト ファイルと同じです。

  2. Java Archive (JAR) または Android Archive (AAR) をプロジェクトに追加し、そのビルド アクションが AndroidLibrary に設定されていることを確認します。

  3. Xamarin.Android バインド ライブラリから変換または追加をコピーします。

サポートされていないレガシ オプション

次の従来のオプションはサポートされなくなりました。 サポートされている代替手段は数年間使用できます。最もスムーズな移行オプションは、.NET に移行する前に、これらのオプションを使用して現在のプロジェクトを更新してテストすることです。

AndroidClassParser

jar2xml は、 $(AndroidClassParser) プロパティの有効なオプションではなくなりました。 class-parse が既定のオプションであり、サポートされているオプションのみです。

class-parse では、次のような、 jar2xmlでは使用できない多くの新しいモダン機能を利用しています。

  • クラス メソッドの自動パラメーター名 (Java コードが javac -parameters でコンパイルされている場合)。
  • Kotlin のサポート。
  • 静的/既定のインターフェイス メンバー (DIM) のサポート。
  • Java nullable 参照型 (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 関連ファイルの globbing 動作は 、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 バインド プロジェクト

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# では、Java の一般的なパターンである interfaceで定数を宣言することは許可されていません。

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# では、入れ子になった型を java で許可されている interfaceで宣言することは許可されていません。

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に対してunnesttrueに設定できます。 これらは常に最上位レベルの型として維持されますが、後で導入される新しい入れ子型はネストされます。

静的および既定のインターフェイス メンバー (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>