Xamarin.Android 绑定到具有依赖项的 3rd 方 SDK

Xamarin.Android Binding to 3rd party SDK with dependencies

我将 VS2015 Update3 与 current/up-to-date Xamarin 一起使用,并尝试创建一个绑定库来包装用 Java 编写的第 3 方 SDK。我有 C#/.Net 背景,到目前为止几乎没有 Java 经验。此 SDK 依赖于其他 3 个项目,它们可作为 AAR 或通过 NuGet 获得。

我能够为父 AAR 创建绑定库,使用一些 MetaData.xml 调整来调整参数类型和 return 类型并更正 class 访问器以满足其抽象base class,所有这些最初都阻止了生成的 C# .Net Android 绑定库的构建。现在父绑定程序集已构建,但无法执行,因为它需要其他 3 个 AAR 依赖项。

需要依赖项(“#”是下面 post 中提到的每个项的别名):

在这种情况下,如果我需要创建绑定 dll 来包装依赖于其他 3 个 AAR 的父 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 文件,然后使用 [=93= 将它们直接包含在 Jars 文件夹中的 Bind_AAR_1.dll 中](或其他attribute/setting)?

或者,看到 2、3 和 4 实际上可以通过 NuGet 获得,我是否应该 (C) 使用 NuGet 将它们引用到 Bind_AAR_1 项目中?如果我使用 NuGet reference/include,AAR 1 中的 Java 代码是否能够看到 AAR 2、3 和 4 中的代码?

我已经尝试了每种方法 (A)、(B) 和 (C) 的变体,但没有成功,或者结果工作导致了更多工作,这让我想知道什么是 best/right 这样做的方法。

在相关主题上,使用 Metadata.xml 文件从生成的包装器 API 中显式删除所有内容(classes 等)是否是最佳实践不打算直接在你的 Xamarin 项目中使用?似乎限制接口并可能减少绑定 dll 的构建大小(以及可能的构建时间)可能会很好。

如有任何帮助,我们将不胜感激!

柯蒂斯

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

2017 年 4 月 11 日 - 更新

很高兴收到@_JonDouglas 等人的意见!但是...仍然无法使此 SDK 正常工作。

我已经尝试了 A、B 和 C 中的每一种方法,并且能够构建我的绑定项目(通过 transforming/MetaData.xml 完成操作)。第 3 方 SDK designed/documented 成为 Java 解决方案的一部分/组件。根据供应商的说明文档,此解决方案会将 3 个依赖项添加到其 .gradle 文件中,从而在整个 Java 解决方案中提供对这些项目的引用。我没有 Java 历史,所以在这里即兴发挥。

事实上,当我使用 Visual Studio 将 SDK(单独或使用 3 种方法中的任何一种的依赖项)包装到 Xamarin Android 绑定程序集时,在运行时 SDK 会遇到 ClassNotFound 异常(由日志中的 "Google Play not found." 证明)。从所需的 Java 依赖项中使用的 classes 是使用 classnames 的名称字符串以后期绑定方式创建的,如下所示: 尝试 { Class.forName("com.google.android.gms.common.GooglePlayServicesUtil");<br> //更多代码在这里 } 赶上(ClassNotFoundException e) { Log.e("第 3 方 SDK", "Google Play not found."); } 我如何使用上述 3 种方法中的任何一种在 Visual Studio 中构建绑定程序集以包含依赖项(1 AAR + 3 Nuget OR 1 AAR + 3 Jars in 1 binding OR 4 AARs in 4 使用项目引用的绑定)。在运行时,SDK 似乎看不到它们。也许这是有道理的,它不会 - 没有 .gradle (如 csproj 文件)在 SDK 本身中指向它们?

我在想我需要做的是(更接近供应商的说明)创建一个 Java 解决方案,其中包含一个 .gradle 文件,其中包含 SDK 以及 3 个依赖项Java 项目,构建以创建 AAR 文件。然后,我相信我可以为生成的包含 AAR 创建一个 Xamarin 绑定程序集。然后我将在我的解决方案中将对此绑定程序集的引用添加到我的 .Andriod 程序集并继续。

理论(尚待证明):[失败。请参阅下面的 4/12 更新。] 将 Java SDK + 其编码依赖项(在 .gradle 中显式)包装在 module/library 中,然后将其包装在 Xamarin [=126= 中] 绑定库。然后我需要做的就是从这个包装器 module/library 中找出我需要使用(并因此公开)哪些 public 方法,添加这些 public 方法并将调用转发给开发工具包。

大图:我正在尝试将其设计和编码为跨平台的 Xamarin 解决方案,但我正在使用 Android 特定和 IOS 特定的 SDK,它们似乎都经过设计成为 application/UI 体验的一部分(旨在做的不仅仅是处理与第 3 方的通信)。这个 UI 方面还没有发挥出来,因为我还没有看到任何一个 SDK 功能。

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

2017 年 4 月 12 日 - 更新

理论(失败):将 Java SDK + 其编码依赖项(在 .gradle 中显式)包装在 module/library 中,然后将其包装在 Xamarin Android 绑定库。我们对此进行了编码、构建、部署和测试。我现在看到该应用程序在运行时进入了 Java 代码的第一层,但找不到任何低于该层的引用代码(也称为依赖项)。包装器的代码运行良好,但运行时包装器找不到 SDK 的 classes,甚至找不到我们试图通过包装器使用的简单 Java 测试组件。这等同于我们最初遇到的 SDK 问题,当时我们只是单独为它创建一个绑定文件,然后通过 JAR 或 NuGet 将其余部分引用到绑定程序集中。下层代码还是没找到,只执行了第一层java。仍在尝试提出解决方案。

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

2017 年 4 月 13 日 - 更新

我取得了一些进步。正如他们所说,前进一步,也许后退两步。

我现在意识到第 3 方 SDK 需要更多 Google 播放服务,而不仅仅是两个依赖项。我反编译了明确提到的两个项目,其中没有命名的 class 。我开始查看本地 Android SDK 位置(在 Visual Studio 中配置)并找到 'play-services-6.5.87.AAR'。将其作为 EmbeddedResourceJar 包含在我的绑定程序集中,最终获得了 SDK 代码以查找上面代码中列出的特定 class。

使用 NuGet

我质疑上述 Java 包装器的价值,因为依赖项所需的一切现在都作为 EmbeddedReferenceJar 包含在内。似乎我应该直接绑定 SDK AAR(不添加 Java 包装层)。我正在重新考虑这一点,并尝试只创建指向 JARS 文件夹中的 SDK AAR 的绑定程序集,然后使用 NuGet 包含 Google Play 服务。

继续,(使用 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

如果我坚持使用 Google 的 'play-services-6.5.87.AAR' 中的 JAR 文件作为 embeddedResourceJar,我不会收到构建错误,但会收到 SDK 可能会出现的运行时错误' 找到 Android 需要的清单设置。如果你有这样安排的项目,我使用的 Android Manifest 是否正确? XXX PCL 项目 --> XXX.Android 项目 <-- 我的猜测是 AndroidManifest.XML 文件所在的位置将被使用....? ----> XXX.Android.AARBinding 项目<br> ------> JARS 文件夹 --> 3pVendorSDK.AAR

还在挖掘....

您应该能够执行 #3,您只需引用 GPS/support 库的这些现有绑定的预构建 NuGet 包。

请确保您使用绑定库期望的确切版本,因为 google 一直移动 类。

我个人推荐的难度顺序如下(简单->困难):

  1. NuGet 包
  2. EmbeddedReferenceJar / ReferenceJar of the .jar or classes.jar (如果有资源就用LibraryProjectZip)
  3. 为每个依赖项绑定项目

作为最佳实践,是的,您应该对您不会使用的项目使用 <remove-node>。但是,这主要用于当您最初不会使用的代码生成错误时。除非有相当多的方法你永远不会接触,否则我会把这些东西放在这儿不管,所以你可以注意你的 dexcount。

如需进一步帮助,您可以查看我的绑定指南:https://gist.github.com/JonDouglas/dda6d8ace7d071b0e8cb

我如何最终让我的第 3 方 Java SDK 与 Xamarin 一起工作:

因为我的解决方案是跨平台的,所以我有:

  • 程序集:MyApplication(PCL 可移植)
  • 程序集:MyApplication.Android
  • 程序集:MyApplication.Android.绑定

    (包装第 3 方 SDK,作为 AAR 文件提供)

相应的 .IOS projects/assemblies 将遵循此命名模式,当我们到达那个时。

Android 绑定程序集

  • Jars 文件夹
    • 包含 My3rdParty.AAR 文件
      设置生成操作:‘LibraryProjectZip‘
  • 转换文件夹
    • Metadata.XML - 我不得不调整 Visual Studio 生成绑定代码的方式,以确保类型对齐等。
    • 我有一些方法返回的类型不能很好地映射到 .Net,所以我使用 attr 元素来调整它们的 'managedType' 和 'managedReturn' 类型值。
      注意:您可以在一种方法上使用多个 attr 元素以根据需要对其进行调整。
    • 我不得不删除一个声明为虚拟的方法(通过使用 remove-node 元素),并将其作为覆盖重新添加到自定义代码中以满足其基础 class 的抽象定义 class.
  • 根文件夹
    • CustomCode.cs - 重新添加需要从私有更改为 public 的方法(已通过 MetaData.xml 删除)。 (请注意,虽然生成的方法将是非功能性的,因为它只是一个满足抽象 class 继承的空存根)

Android 大会

  • 清单

    • 缺少 accurate/complete SDK 清单文档。
      在 Android 程序集中对 Sdk 清单信息进行了更改。
  • 参考文献

    • 添加对 Android 绑定程序集的引用。
  • 组件 (NuGet)

    • 由于我的第 3 方的 SDK 记录了对 Google Play 服务的依赖性,并且我使用 JD-GUI 反编译了他们的代码以验证 classes/etc 它试图使用什么,我添加了 Xamarin.GooglePlayServices.Gcm 这个项目,而不是绑定程序集项目

      注意:我在任何文档中都不清楚我会阅读什么级别来引入 AAR 的依赖项。在我的许多尝试之一中,我沿着路径将它们作为 JAR 直接(从 AAR 中提取)添加到 Binding Assembly 的 JARS 文件夹中,BuildAction 为 EmbeddedResourceJar。这提供了稍微更好的 运行-time 结果,因为找到了所需的项目,但感觉......令人作呕......似乎是维护问题的秘诀。必须有更好的方法。输入 NuGet!

      注意:添加这一项会带来以下所有项目:
    • Xamarin.GooglePlayServices.Base
    • Xamarin.GooglePlayServices.Base转
    • Xamarin.GooglePlayServices.Gcm(通过VS Manage NuGet添加的)
    • Xamarin.GooglePlayServices.Iid
    • Xamarin.GooglePlayServices.Tasks
  • 资产

    • 我的 3rd Party 的 SDK 使用了一个 config.JSON 文件,需要将其放在这里以便在 运行 时它可以读取它。
      设置构建操作:‘Android资产’
  • 构建时间需要额外的工作:

    • 绑定组件中的其他 MetaData.XML 更改。
      - 一些生成的代码在此时发生 new 构建错误,当编译的绑定程序集被 Android 程序集引用并且构建是尝试过。

程序集绑定转换

如上所述,当我构建 MyApplication.Android.Binding 时,它自己构建得很好。但是,当我在 MyApplication.Android 中引用它时,它生成了一个新的 Java 代码转换构建错误,关于特定 class 的范围不是 expected/required。为了解决这个问题,我回到 Binding 程序集的 MetaData.xml 文件并选择从生成的 Java 代码接口中删除问题 class 因为我没有计划调用或使用。

提示:在 Visual Studio 中执行此操作(我发现)的最简单方法是在 BindingAssembly 项目上启用“显示所有文件”功能,然后查看 obj\Debug\generated\src\问题的文件夹 class。找到它后,单击它,生成的 Java 接口代码会将生成的 XPath 语句作为注释。这些是您使用 MetaData.XML 文件更改或消除问题 classes 或方法所需要的。

总结

现在我需要做的就是在上面编写我的跨平台代码(使用依赖倒置 + Xamarin Forms 内置 DependencyService 在 运行 时间到达每个 SDK)我的应用程序应该很好去吧!

希望这些发现对需要处理类似绑定场景的其他人有所帮助。

如果您确实看到这里的任何内容不正确,或者如果您有任何要添加的内容,请发表评论!