Привязка Xamarin.Android к стороннему пакету SDK с зависимостями

Я использую VS2015 Update3 с текущим/актуальным Xamarin и пытаюсь создать библиотеку привязок для переноса стороннего SDK, написанного на Java. У меня есть опыт работы с C#/.Net, пока у меня мало опыта работы с Java. Этот SDK зависит от 3 других элементов, которые доступны в виде AAR или через NuGet.

Мне удалось создать библиотеку привязок для родительского AAR с некоторой настройкой MetaData.xml для настройки типов параметров и возвращаемых типов и исправления метода доступа к классу, чтобы он удовлетворял его абстрактному базовому классу, все из которых изначально препятствовали результирующему C# .Net Android привязка библиотеки из здания. Теперь родительская сборка привязки создается, но не может выполняться, так как для этого требуются другие 3 зависимости AAR.

Необходимые зависимости ("#" - это псевдоним для каждого, когда он упоминается в сообщении ниже):

  • «2» -> com.android.support:support-v4:25.1.1
  • "3" -> com.google.android.gms:play-services-location:10.2.0
  • «4» -> com.google.android.gms:play-services-gcm:10.2.0

В этом сценарии, если мне нужно создать привязку dll для переноса родительского AAR, который зависит от 3 других AAR:

Должен ли я (A) создать 4 сборки привязки — родительскую сборку привязки Bind_AAR_1.dll, которая зависит от Bind_AAR_2.dll, Bind_AAR_3.dll и Bind_AAR_4.dll?

ИЛИ, должен ли я (B) копаться в файлах 2, 3 и 4 AAR и получать файлы JAR из каждого, а также включать их в Bind_AAR_1.dll непосредственно в папку Jars, используя «EmbeddedJar» (или другой атрибут/параметр)?

ИЛИ, учитывая, что 2, 3 и 4 действительно доступны через NuGet, должен ли я (C) ссылаться на них в проекте Bind_AAR_1 с помощью NuGet? Сможет ли Javacode в AAR 1 видеть код в AAR 2, 3 и 4, если я использую NuGet для ссылки на них/включения?

Я пробовал вариации каждого из методов (A), (B) и (C), пока безуспешно или в результате работы, которая приводит к дополнительной работе, что заставляет меня задаться вопросом, как лучше/правильный способ сделать это.

Что касается связанной темы, рекомендуется ли использовать файл Metadata.xml для явного удаления всего (классы и т. д.) из созданного API-интерфейса-оболочки, который вы не планируете использовать напрямую в своем проекте Xamarin? Похоже, было бы неплохо ограничить интерфейс и, возможно, также уменьшить размер сборки (и, возможно, время сборки) связывающей dll.

Любая помощь будет оценена по достоинству!

Кертис

=======================================================================

11.04.2017 — Обновление

Очень рад получить информацию от таких людей, как @_JonDouglas! но... до сих пор не удалось заставить этот SDK работать.

Я пробовал каждый из этих методов A, B и C и смог собрать свой проект привязок (с манипуляциями, выполненными с помощью преобразования/MetaData.xml). Сторонний SDK был разработан/задокументирован как часть/компонент решения Java. Согласно учебной документации поставщика, это решение будет иметь 3 зависимости, добавленные в его файл .gradle, таким образом предоставляя ссылку на эти элементы в общем решении Java. У меня нет истории Java, поэтому пишу ее здесь.

Как бы то ни было, когда я оборачиваю SDK (отдельно или с зависимостями, используя любой из трех методов) с помощью Visual Studio в Xamarin Android Binding Assembly, во время выполнения SDK попадает в исключения ClassNotFound (о чем свидетельствует «Google Play не найден» в журналы). Классы, используемые из требуемых зависимостей Java, создаются поздней привязкой с использованием строк имен для имен классов, например: элементы зависимостей (1 AAR + 3 Nuget ИЛИ 1 AAR + 3 JAR в 1 привязке ИЛИ 4 AAR в 4 привязках с использованием ссылок на проекты). Во время выполнения SDK их не видит. Возможно, это имеет смысл, потому что это не так - в самом SDK нет .gradle (например, файла csproj), который указывает на них?

Я думаю, что мне нужно сделать (ближе к инструкции поставщика) создать решение Java с файлом .gradle, который включает SDK, а также 3 зависимости в проекте Java, создавая файл AAR. Затем я полагаю, что смогу создать сборку привязки Xamarin для полученного включающего AAR. Затем я добавлю ссылку на эту сборку привязки в свою сборку .Andriod в своем решении и продолжу.

Теория (еще не доказанная): [Не удалось. См. обновление от 12 апреля ниже.] Оберните пакет SDK для Java и его закодированные зависимости (явные в .gradle) в модуль/библиотеку, а затем оберните их в библиотеку Xamarin Android Binding. Затем все, что мне нужно сделать, это выяснить, какие общедоступные методы мне нужно использовать (и, следовательно, выставлять) из этого модуля/библиотеки-оболочки, добавить эти общедоступные методы и перенаправить вызовы в SDK.

Общая картина: я пытаюсь спроектировать и закодировать это как кросс-платформенное решение Xamarin, но я работаю с SDK для Android и для IOS, которые, по-видимому, предназначены для того, чтобы быть частью взаимодействия с приложением / пользовательским интерфейсом (предназначенным для выполнения больше, чем просто обработка связи с третьей стороной). Этот аспект пользовательского интерфейса еще не реализован, так как я еще не видел ни одну из функций SDK.

=======================================================================

12.04.2017 — Обновление

Теория (НЕУДАЧА): оберните Java SDK + его закодированные зависимости (явно указанные в .gradle) в модуль/библиотеку, а затем оберните их в библиотеку Xamarin Android Binding. Мы закодировали, построили, развернули и протестировали это. Теперь я вижу, что приложение во время выполнения попадает в первый уровень кода Java, но не может найти какой-либо ссылочный код ниже этого (он же зависимости). Код оболочки работает нормально, но оболочка во время выполнения не может найти ни классы SDK, ни даже простой тестовый компонент Java, который мы пытались использовать через оболочку. Это эквивалентно проблеме, которая возникла у нас с SDK в первую очередь, когда мы просто создали файл привязки только для него и ссылались на остальные в сборку привязки с помощью JAR или через NuGet. Код нижнего уровня по-прежнему не найден, выполняется только первый слой java. Все еще пытаюсь найти решение.

=======================================================================

13.04.2017 — Обновление

Я добился определенного прогресса. Как говорится, шаг вперед и, может быть, два шага назад.

Теперь я понимаю, что стороннему SDK требуется больше сервисов Google Play, чем просто две зависимости. Я декомпилировал два явно упомянутых элемента, и именованного класса там нет. Я начал искать локальное местоположение Android SDK (как настроено в Visual Studio) и нашел «play-services-6.5.87.AAR». Включение этого в мою сборку привязки в качестве EmbeddedResourceJar наконец-то дало код SDK для поиска конкретного класса, указанного в коде выше.

Использование NuGet

Я сомневаюсь в ценности описанной выше Java-оболочки, поскольку все, что нужно для зависимостей, теперь включено в виде EmbeddedReferenceJar. Похоже, я должен просто связать SDK AAR напрямую (без добавления слоя оболочки Java). Я переосмысливаю это и пытаюсь просто создать сборку привязки, указывающую на SDK AAR в папке JARS, а затем включить службы Google Play с помощью NuGet.

Продолжая это (используя NuGet для ссылки на сервисы Google Play), я теперь получаю эту ошибку: No resource found that matches the given name (at 'value' with value '@integer/google_play_services_version'). {project name} {project path}\AndroidManifest.xml Я пробовал МНОГО разных вещей, чтобы попытаться избавиться от этой ошибки времени сборки, но мне не повезло.

Не используя NuGet

Если я буду использовать файл JAR из Google play-services-6.5.87.AAR в качестве встроенного ресурсаResourceJar, я не получаю ошибок сборки, но получаю ошибки времени выполнения, которые SDK не может найти манифест Android нужны настройки. Если у вас есть такой проект, правильно ли я понимаю, какой манифест Android используется? XXX PCL Project --> XXX.Android project <-- My guess is that this is where the AndroidManifest.XML file is located that will be used....? ----> XXX.Android.AARBinding project
------> JARS folder --> 3pVendorSDK.AAR

Еще копаю....


person Curtis Herrick    schedule 06.04.2017    source источник


Ответы (2)


Как я наконец заставил свой сторонний Java SDK работать с Xamarin:

Поскольку мое решение должно быть кроссплатформенным, у меня есть:

  • Сборка: MyApplication (PCL Portable)
  • Сборка: MyApplication.Android
  • Сборка: MyApplication.Android.Binding

    (обертка стороннего SDK, предоставленного в виде файла AAR)

Соответствующие проекты/сборки .IOS будут следовать этому шаблону именования, когда мы доберемся до этого.

Сборка привязки Android

  • Jars Folder
    • Include My3rdParty.AAR file
      Set with Build Action: ‘LibraryProjectZip‘
  • Transforms Folder
    • Metadata.XML - I had to make adjustments to how the binding code was to be generated by Visual Studio to make sure types align, etc.
    • У меня было несколько методов, которые возвращали типы, которые плохо отображались в .Net, поэтому я использовал элементы attr для настройки их значений типов «managedType» и «managedReturn».
      Примечание. Вы можете использовать более одного attr. элемент в одном методе, чтобы настроить его по желанию.
    • Мне пришлось удалить метод (с помощью элемента remove-node), который был объявлен как виртуальный, и повторно добавить его в пользовательский код в качестве переопределения, чтобы удовлетворить определение абстрактного класса его базового класса.
  • Root Folder
    • CustomCode.cs - Re-add the one method that needed to be changed from private to public (it was removed via MetaData.xml). (note though that the resulting method will be non-functional, as it is just an empty stub to satisfy the abstract class inheritance)

Сборка Android

  • Манифест

    • Lacked accurate/complete SDK Manifest documentation.
      The Sdk manifest info changes were made here in the Android Assembly.
  • Рекомендации

    • Add a reference to the Android Binding Assembly.
  • Компоненты (NuGet)

    • Since my 3rd Party's SDK had documented dependencies on Google Play Services, and I'd decompiled their code using JD-GUI to verify what classes/etc it was trying to use, I added Xamarin.GooglePlayServices.Gcm to this project, not the Binding Assembly project.

      Note: It wasn't clear to me in any documentation that I'd read what level to bring in the AAR's dependencies. In one of my many attempts, I had gone down the path of adding them as JAR's directly (extracted from AAR's) to the Binding Assembly's JARS folder with a BuildAction of EmbeddedResourceJar. This provided slightly better run-time results as required items were found, but it felt... icky... Seemed like a recipe for maintenance issues. There had to be a better way. Enter NuGet!

      Note: Adding this one item brings along all of the following items:
    • Xamarin.GooglePlayServices.Base
    • Xamarin.GooglePlayServices.Подвал
    • Xamarin.GooglePlayServices.Gcm (добавленный через VS Manage NuGet)
    • Xamarin.GooglePlayServices.Iid
    • Xamarin.GooglePlayServices.Tasks
  • Ресурсы

    • My 3rd Party's SDK used a config.JSON file, which needed to be put here so that at runtime it can read it.
      Set with Build Action: ‘AndroidAsset’
  • Время сборки Необходима дополнительная работа:

    • Additional MetaData.XML changes in the Binding Assembly.
      - Some of the generated code had new build errors that occurred at this point, when the compiled Binding Assembly is referenced by the Android assembly and a build was attempted.

Преобразования привязки сборки

Как указывалось выше, когда я собрал MyApplication.Android.Binding, он сам по себе отлично собрался. Однако, когда я сослался на него в MyApplication.Android, он сгенерировал новую ошибку сборки перевода кода Java о том, что область действия определенного класса не соответствует ожидаемому/необходимому. Чтобы решить эту проблему, я вернулся к файлу MetaData.xml сборки Binding и решил удалить проблемный класс из сгенерированного интерфейса кода Java, поскольку у меня не было планов вызывать или использовать его.

СОВЕТ. Самый простой способ сделать это (который я нашел) в Visual Studio — включить функцию «Показать все файлы» в проекте BindingAssembly, а затем просмотреть папки obj\Debug\generated\src\ для класса задачи. Как только вы найдете его, щелкните по нему, и в сгенерированном коде интерфейса Java будут операторы XPath, сгенерированные в виде комментариев. Это то, что вам нужно, чтобы изменить или удалить проблемные классы или методы с помощью файла MetaData.XML.

Заворачивать

Теперь все, что мне нужно сделать, это написать мой кросс-платформенный код сверху (используя Dependency Inversion + Xamarin Forms, встроенный DependencyService для доступа к каждому пакету SDK во время выполнения), и мое приложение готово к работе!

Надеемся, что эти выводы будут полезны другим, которым необходимо работать с аналогичным сценарием привязки.

Если вы видите здесь неверный контент или хотите что-то добавить, пожалуйста, прокомментируйте!

person Curtis Herrick    schedule 25.04.2017

Вы должны быть в состоянии сделать № 3, в котором вы просто ссылаетесь на предварительно созданные пакеты NuGet этих существующих привязок библиотек GPS/поддержки.

Убедитесь, что вы используете именно ту версию, которую ожидает библиотека привязки, поскольку Google постоянно перемещает классы.

Моя личная рекомендация следующая в порядке сложности (легко -> сложно):

  1. NuGet-пакет
  2. EmbeddedReferenceJar / ReferenceJar из .jar или classes.jar (используйте LibraryProjectZip, если есть ресурсы)
  3. Связывание проектов для каждой зависимости

Лучше всего да, вы должны использовать <remove-node> для элементов, которые вы не будете использовать. Однако это в основном используется, когда ошибки генерируются кодом, который вы не будете использовать в первую очередь. Я бы просто хранил предметы здесь, если только не существует довольно много методов, которые вы никогда не будете трогать, поэтому вы можете помнить о своем счете.

Для получения дополнительной помощи вы можете просмотреть мое руководство по привязкам: https://gist.github.com/JonDouglas/dda6d8ace7d071b0e8cb< /а>

person Jon Douglas    schedule 06.04.2017
comment
Добавлено обновление 4/12. Идея обернуть зависимости SDK + в компонент Java не сработала. Все еще пытаюсь найти решение. - person Curtis Herrick; 12.04.2017
comment
У кого-нибудь есть пример привязки к чему-то, что зависит от внешних элементов, таких как Google Play Services? - person Curtis Herrick; 14.04.2017
comment
Извините - я должен уточнить. Я имел в виду использование компонента через сборку привязки (например, обертывание AAR), где компонент, обернутый, использует сервисы Google Play. Мой исходный вопрос был обновлен 4/13, а также с дополнительной информацией. - person Curtis Herrick; 14.04.2017
comment
После добавления сервисов Google Play в мой проект привязки (через NuGet или через EmbeddedReferenceJar) я получаю эту ошибку, когда пытаюсь создать свой проект, который будет использовать сборку привязки: No resource found that matches the given name (at 'value' with value '@integer/google_play_services_version'). Я пытался извлечь версию .xml из AAR сервисов Google Play и найти его внутри моего проекта в таких местах, как Resources\Values\version.xml, но он не отображается во время выполнения. - person Curtis Herrick; 14.04.2017