Xamarin.Android绑定到具有依赖项的第三方SDK

我正在使用VS2015 Update3与当前/最新的Xamarin,我正在尝试创建一个绑定库来包装用Java编写的第三方SDK。 我有一个C#/ .Net背景,到目前为止几乎没有Java经验。 此SDK依赖于3个其他项目,可以作为AAR或通过NuGet获得。

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

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

  • “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来包装依赖于3个其他AAR的父AAR:

我应该(A)创建4个绑定程序集 – 父绑定程序集Bind_AAR_1.dll,它依赖于Bind_AAR_2.dll,Bind_AAR_3.dll和Bind_AAR_4.dll?

或者,我是否应该(2)深入研究2个,3个和4个AAR文件并从每个文件中获取JAR文件,并使用“EmbeddedJar”(或其他属性/设置)将它们直接包含在Jars文件夹中的Bind_AAR_1.dll中?

或者,看到2,3和4实际上是通过NuGet提供的,我应该使用NuGet将它们引用到Bind_AAR_1项目吗? 如果我使用NuGet引用/包含它们,那么AAR 1中的Javacode是否能够看到AAR 2,3和4中的代码?

我已经尝试了各种方法(A),(B)和(C)的变化,但没有运气,或导致更多工作的结果,这让我想知道什么是最好/正确的方法。

在相关主题上,最佳做法是使用Metadata.xml文件从生成的生成的包装器API中显式删除您未直接计划在Xamarin项目中使用的所有内容(类等)吗? 似乎限制接口可能是好的,并且可能还减少绑定dll的构建大小(以及可能的构建时间)。

任何帮助,将不胜感激!

柯蒂斯

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

4/11/2017 – 更新

非常高兴收到@_JonDouglas之类的投入! 但是……仍然无法使这个SDK工作。

我已经尝试了这些方法A,B和C中的每一个,并且已经能够构建我的绑定项目(通过转换/ MetaData.xml完成​​操作)。 第三方SDK被设计/记录为Java解决方案中的组件的一部分。 根据供应商的说明文档,此解决方案将在其.gradle文件中添加3个依赖项,从而在整个Java解决方案中提供对这些项的引用。 我没有Java历史,所以在这里展开它。

实际上,当我将SDK(单独使用或使用3种方法中的任何一种)与Visual Studio包装到Xamarin Android绑定程序集中时,在运行时SDK会遇到ClassNotFoundexception(由“未找到Google Play”certificate)日志)。 从所需的Java依赖项中使用的类是以后期绑定的方式使用类名的名称字符串创建的,如下所示: try { Class.forName("com.google.android.gms.common.GooglePlayServicesUtil");
//more code here } catch (ClassNotFoundException e) { Log.e("3rd Party SDK", "Google Play not found."); }
try { Class.forName("com.google.android.gms.common.GooglePlayServicesUtil");
//more code here } catch (ClassNotFoundException e) { Log.e("3rd Party SDK", "Google Play not found."); }
使用上述3种方法中的任何一种在Visual Studio中构建绑定程序集似乎并不重要,包括依赖项(1个绑定中的1个AAR + 3个Nuget OR 1个AAR + 3个JAR或4个绑定中的4个AAR)使用项目参考)。 在运行时,SDK似乎没有看到它们。 也许这是有意义的,它不会 – 在SDK本身没有.gradle(如csproj文件)指向它们?

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

理论(尚未证实):[失败。 请参阅下面的4/12更新。]将Java SDK +编码的依赖项(在.gradle中显式)包装在模块/库中,然后将其包装在Xamarin Android Binding库中。 然后,我需要做的就是从这个包装器模块/库中找出我需要使用的公共方法(并因此公开),添加这些公共方法并将调用转发给SDK。

大图:我正在尝试将其设计和编码为跨平台的Xamarin解决方案,但我正在使用特定于Android和IOS的SDK,这些SDK看起来都是应用程序/ UI体验的一部分(旨在实现不只是处理与第三方的沟通)。 这个UI方面尚未发挥作用,因为我还没有看到任何SDKfunction。

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

2017/12/12 – 更新

理论(FAILED):在模块/库中包装Java SDK +其编码依赖项(在.gradle中显式),然后将其包装在Xamarin Android Binding库中。 我们对此进行了编码,构建,部署和测试。 我现在看到应用程序在运行时进入第一层Java代码,但未能找到任何低于该代码的引用代码(也称为依赖项)。 包装器的代码运行正常,但运行时的包装器无法找到SDK的类,甚至也没有找到我们尝试通过包装器使用的简单Java测试组件。 当我们单独为它创建一个绑定文件时,这相当于我们首先使用SDK的问题,并通过JAR或NuGet将其余部分引用到绑定程序集中。 仍未找到较低级别的代码,只执行第一层java。 仍在努力想出一个解决方案。

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

4/13/2017 – 更新

我取得了一些进展。 向前迈出一步,也许正如他们所说的那样两步回来。

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

使用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 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 Project --> XXX.Android project XXX.Android.AARBinding project
------> JARS folder --> 3pVendorSDK.AAR

还在挖……

我最终如何让我的第三方Java SDK与Xamarin一起使用:

由于我的解决方案是跨平台,我有:

  • 汇编:MyApplication(PCL Portable)
  • 汇编:MyApplication.Android
  • 汇编:MyApplication.Android.Binding

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

当我们达到目的时,各个.IOS项目/程序集将遵循这种命名模式。

Android绑定程序集

  • jar子文件夹
    • 包含My3rdParty.AAR文件
      使用Build Action设置:’LibraryProjectZip’
  • 转换文件夹
    • Metadata.XML – 我必须调整Visual Studio如何生成绑定代码以确保类型对齐等。
    • 我有一些方法返回的类型没有很好地映射到.Net,所以我使用attr元素来调整它们的’managedType’和’managedReturn’类型值。
      注意:您可以在一个方法上使用多个attr元素,以根据需要进行调整。
    • 我不得不删除一个声明为virtual的方法(通过使用remove-node元素),并在自定义代码中重新添加它作为覆盖,以满足其基类的抽象类定义。
  • 根文件夹
    • CustomCode.cs – 重新添加需要从私有更改为public的方法(通过MetaData.xml删除)。 (请注意,结果方法将不起作用,因为它只是一个空的存根来满足抽象类inheritance)

Android大会

  • 表现

    • 缺乏准确/完整的SDK Manifest文档。
      Sdk清单信息更改是在Android程序集中进行的。
  • 参考

    • 添加对Android Binding Assembly的引用。
  • 组件(NuGet)

    • 由于我的第三方SDK已经记录了对Google Play服务的依赖性,并且我使用JD-GUI反编译他们的代码以validation它试图使用的类/等,我将Xamarin.GooglePlayServices.Gcm添加到此项目中 ,而不是绑定assembly项目

      注意:我在任何文档中都不清楚我是否已经阅读了引入AAR依赖关系的级别。 在我的许多尝试之一中,我已经沿着将JAR直接(从AAR中提取)添加到Binding Assembly的JARS文件夹的路径,其中包含BuildAction的EmbeddedResourceJar。 这提供了稍微更好的运行时结果,因为找到了所需的项目,但它感觉…… icky ……看起来像维护问题的配方。 必须有一个更好的方法。 进入NuGet!

      注意:添加此项目会带来以下所有项目:

    • Xamarin.GooglePlayServices.Base
    • Xamarin.GooglePlayServices.Basement
    • Xamarin.GooglePlayServices.Gcm(通过VS Manage NuGet添加的一个)
    • Xamarin.GooglePlayServices.Iid
    • Xamarin.GooglePlayServices.Tasks
  • 资产

    • 我的第三方SDK使用了一个config.JSON文件,需要放在这里,以便在运行时它可以读取它。
      使用构建操作设置:’AndroidAsset’
  • 构建时间需要额外的工作:

    • 绑定程序集中的其他MetaData.XML更改。
      – 当Android程序集引用编译的绑定程序集并尝试构建时,某些生成的代码会出现此时发生的构建错误。

assembly绑定变换

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

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

包起来

现在我需要做的就是在顶层编写我的跨平台代码(使用Dependency Inversion + Xamarin Forms内置DependencyService来在运行时访问每个SDK),我的应用程序应该很好用!

希望这些发现对需要通过类似绑定方案工作的其他人有所帮助。

如果您确实在此处看到任何不正确的内容,或者您​​有任何想要添加的内容,请发表评论!

你应该能够做#3,你只需要参考这些现有的GPS /支持库绑定的预建NuGet包。

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

我的个人建议是按照以下顺序排列(简单 – >难):

  1. NuGet包
  2. .jarclasses.jar EmbeddedReferenceJar / ReferenceJar (如果有resoruces,请使用LibraryProjectZip
  3. 为每个依赖项绑定项目

作为最佳实践,是的,您应该对不会使用的项目使用 。 但是,这主要用于首先不使用的代码生成错误时。 无论如何我都会保留这些物品,除非有很多方法你永远不会碰到所以你可以留意你的dexcount。

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