Миграция проекта привязки Xamarin.Android
В .NET отсутствует концепция проекта привязки Android в качестве отдельного типа проекта. Любые группы элементов MSBuild или действия сборки, которые работают в проектах привязки Xamarin.Android, поддерживаются с помощью приложения или библиотеки .NET для Android.
Чтобы перенести библиотеку привязок Xamarin.Android в библиотеку классов .NET для Android:
В Visual Studio создайте проект привязки библиотеки Java для Android с тем же именем, что и проект привязки Xamarin.Android:
Открытие файла проекта подтвердит наличие проекта в стиле пакета SDK для .NET:
<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).
- Поддержка примечаний ссылочного типа (NRT) для Java NULL.
AndroidCodegenTarget
XamarinAndroid
Больше не является допустимым параметром $(AndroidCodegenTarget)
для свойства. XAJavaInterop1
теперь используется параметр по умолчанию и поддерживается только для этого параметра.
Если у вас есть ручной код в Additions
файлах, взаимодействующих с созданным кодом привязки, его может потребоваться обновить, чтобы быть совместимым с XAJavaInterop1
.
Включение файлов по умолчанию
Учитывая следующую структуру файлов:
Transforms/
Metadata.xml
foo.jar
Transforms\*.xml
файлы автоматически включаются в качестве @(TransformFile)
элемента, а.aar
.jar
/файлы автоматически включаются в качестве @(AndroidLibrary)
элемента. Это привязывает типы C# для типов Java, найденных при foo.jar
использовании исправлений метаданных из Transforms\Metadata.xml
.
Поведение глоббинга файлов android по умолчанию определяется в autoImport.props. Это поведение можно отключить для элементов Android, присвоив $(EnableDefaultAndroidItems)
свойству 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 |
Н/Д | Проект привязки |
EmbeddedReferenceJar |
AndroidLibrary |
Bind="false" |
Проект привязки |
InputJar |
AndroidLibrary |
Pack="false" |
Проект привязки |
LibraryProjectZip |
AndroidLibrary |
Н/Д | Проект привязки |
Рассмотрим .aar
или .jar
файл, в котором вы не заинтересованы, включая привязку C#. Это часто происходит в тех случаях, когда у вас есть зависимости Java или Kotlin, которые не нужно вызывать из C#. В этом случае можно задать Bind
для метаданных false
значение . По умолчанию файл выбирается по умолчанию дикими карта. Атрибут можно также использовать Update
для задания Bind
метаданных:
<ItemGroup>
<AndroidLibrary Update="foo.jar" Bind="false">
</ItemGroup>
В проекте библиотеки классов Android этот файл будет распространяться .jar
внутри результирующего пакета NuGet как есть. В проекте приложения Android это будет включать .jar
файл в результирующий .apk
или .aab
файл. Ни в коем случае не будет включать привязку C# для этой библиотеки Java.
Внедренные 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. Однако при переносе существующего проекта привязки эти функции могут создавать привязки, несовместимые с существующими привязками. Для обеспечения совместимости может потребоваться отключить или изменить эти новые функции.
Константы интерфейса
Традиционно 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# не разрешает объявлять вложенные типы в 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
и задать true
unnest
для каждого interface
из вложенных типов, которые в настоящее время есть. Они всегда будут оставаться типами верхнего уровня, а все новые вложенные типы, представленные позже, будут вложены.
Статические и стандартные элементы интерфейса (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 () { ... }
}
Однако это означает, что альтернативный одноуровневый элемент class
, содержащий static
элементы, больше не будет создан.
$AndroidBoundInterfacesContainStaticAndDefaultInterfaceMethods
Установка свойства false
в файле проекта будет отменить изменения в устаревшем поведении.
Ссылочные типы, допускающие значение null
Добавлена поддержка ссылочных типов, допускающих значение NULL (NRT), в Xamarin.Android 11.0. Поддержка NRT может быть включена с помощью стандартного механизма .NET:
<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
имен и недопустимому C# в 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
Чтобы отключить Resource.designer.cs
создание, задайте $(AndroidGenerateResourceDesigner)
для свойства false
значение в файле проекта:
<PropertyGroup>
<AndroidGenerateResourceDesigner>false</AndroidGenerateResourceDesigner>
</PropertyGroup>