Xamarin.Android 绑定到具有依赖项的 3rd 方 SDK [英] Xamarin.Android Binding to 3rd party SDK with dependencies

查看:36
本文介绍了Xamarin.Android 绑定到具有依赖项的 3rd 方 SDK的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using VS2015 Update3 with current/up-to-date Xamarin, and am trying to create a binding library to wrap a 3rd party SDK written in Java. I have a C#/.Net background, with little Java experience thus far. This SDK depends on 3 other items, which are available as AAR's or via NuGet.

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

I was able to create a binding library for the parent AAR, with some MetaData.xml tweakery to adjust parameter types and return types and correct a class accessor to satisfy its abstract base class, all of which were initially preventing the resulting C# .Net Android binding library from building. Now the parent binding assembly builds, but can't execute, as it requires the other 3 AAR dependencies.

需要依赖项(#"是下面帖子中提到的每个项的别名):

Dependencies needed ("#" is the alias for each when mentioned in the post below):

  • "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:

In this scenario, if I need to create a binding dll to wrap a parent AAR that depends on 3 other AARs:

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

Should I (A) create 4 binding assemblies - a parent binding assembly Bind_AAR_1.dll, that depends on Bind_AAR_2.dll, Bind_AAR_3.dll, and Bind_AAR_4.dll?

或者,我应该 (B) 深入研究 2、3 和 4 个 AAR 文件并从每个文件中获取 JAR 文件,并使用EmbeddedJar"(或其他属性/设置)?

OR, should I (B) dig into the 2, 3, and 4 AAR files and get the JAR file from each, and include them in Bind_AAR_1.dll directly in the Jars folder using 'EmbeddedJar' (or other attribute/setting)?

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

OR, seeing that 2, 3, and 4 are actually availabe via NuGet, should I (C) reference them into the Bind_AAR_1 project using NuGet? Will the Javacode in the AAR 1 be able to see the code in AAR's 2, 3, and 4 if I use NuGet to reference/include them?

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

I've tried variations on each of methods (A), (B), and (C) with no luck yet, or resulting work that leads to more work, which leaves me wondering what is the best/right way to do this.

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

On a related topic, is it a best practice to use the Metadata.xml file to explicitly remove everything (classes, etc) from the resulting generated wrapper API that you do not directly plan to use in your Xamarin project? Seems like it might be good to limit the interface and perhaps also reduce the build size (and possibly build time) of the binding dll.

任何帮助将不胜感激!

柯蒂斯

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

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

4/11/2017 - 更新

4/11/2017 - Update

很高兴收到@_JonDouglas 之类的意见!但是...仍然无法让这个 SDK 工作.

Very glad to have input from the likes of @_JonDouglas! but... still not able to get this SDK working.

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

I have tried each of these methods A, B, and C, and have been able to get my bindings project to build (with manipulations done via transforming/MetaData.xml). The 3rd party SDK was designed/documented to be a part of / a component in a Java solution. Per the vendor's instructional documentation, this solution would have the 3 dependencies added to its .gradle file, thus providing the reference to these items in the overall Java solution. I have no Java history, so winging it here.

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

As it is, when I wrap the SDK (alone or with dependencies using any of the 3 methods) with Visual Studio into a Xamarin Android Binding Assembly, at runtime the SDK hits ClassNotFound exceptions (evidenced by "Google Play not found." in the logs). The classes used from the required Java dependencies are created created in a late bound fashion using name strings for classnames like this: try { Class.forName("com.google.android.gms.common.GooglePlayServicesUtil");
//more code here } catch (ClassNotFoundException e) { Log.e("3rd Party SDK", "Google Play not found."); }
It doesn't seem to matter how I build the binding assembly in Visual Studio using any of the 3 methods above to include the dependency items (1 AAR + 3 Nuget OR 1 AAR + 3 Jars in 1 binding OR 4 AARs in 4 bindings using project references). At runtime, the SDK doesn't seem to see them. Perhaps that makes sense that it won't - there's no .gradle (like a csproj file) that points to them in the SDK itself?

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

I am thinking what I need to do is (closer to the vendor's instruction) create a Java solution complete with a .gradle file that includes the SDK as well as the 3 dependencies in the Java project, building to create an AAR file. Then, I believe I may be able to create a Xamarin binding assembly for the resulting encompasing AAR. Then I'll add a reference to this binding assembly to my .Andriod assembly within my solution and proceed.

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

Theory (yet to be proven): [Failed. See 4/12 update below.] Wrap the Java SDK + its coded dependencies (explicit in the .gradle) in a module/library, and then wrapping that in a Xamarin Android Binding library. Then all I'll need to do is figure out what public methods I need to use (and therefore expose) from this wrapper module/library, add these public methods and forward the calls to the SDK.

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

Big Picture: I'm trying to design and code this as a cross-platform Xamarin solution, but am working with an Android-specific and IOS-specific SDK that appear both designed to be part of the application/UI experience (designed to do more than just handle communication to the 3rd party). This UI aspect has yet to play out, as I've not seen either SDK function as of yet.

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

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

4/12/2017 - 更新

4/12/2017 - Update

理论(失败):将 Java SDK 及其编码依赖项(在 .gradle 中明确显示)包装在模块/库中,然后将其包装在 Xamarin Android 绑定库中.我们对此进行了编码、构建、部署和测试.我现在看到应用程序在运行时进入 Java 代码的第一层,但未能找到任何低于该层的引用代码(也称为依赖项).包装器的代码运行良好,但运行时的包装器找不到 SDK 的类,甚至找不到我们试图通过包装器使用的简单 Java 测试组件.这相当于我们首先为 SDK 创建了一个绑定文件,然后通过 JAR 或通过 NuGet 将其余部分引用到绑定程序集中时,我们遇到的问题.还没有找到更底层的代码,只执行了第一层java.仍在努力想出一个解决方案.

Theory (FAILED): Wrap the Java SDK + its coded dependencies (explicit in the .gradle) in a module/library, and then wrap that in a Xamarin Android Binding library. We coded, built, deployed, and tested this. I now see that the app at runtime gets into the first layer of Java code, but fails to find any referenced code lower than that (aka dependencies). The wrapper's code runs fine but the wrapper at runtime can't find the SDK's classes, nor even a simple Java test component that we attempted to use via the wrapper. This is equivalent to issue we had with the SDK in the first place when we simply created a bindings file for it alone, and referenced the rest into the binding assembly by JAR or via NuGet. The lower level code is still not found, only the first layer of java executes. Still trying to come up with a solution.

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

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

4/13/2017 - 更新

4/13/2017 - Update

我取得了一些进展.正如他们所说,向前迈出一步,也可能向后退两步.

I have made some progress. One step forward, and maybe two steps back as they say.

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

I now realize that the 3rd party SDK needs more of Google Play Services than just the two dependencies. I decompiled the two items explicitly mentioned, and the named class is not in there. I started looking at the local Android SDK location (as configured in Visual Studio) and found 'play-services-6.5.87.AAR'. Including this in my binding assembly as an EmbeddedResourceJar finally got the SDK code to find the particular class listed in code above.

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

I am questioning the value of the Java wrapper described above, since everything needed for dependencies is now included as an EmbeddedReferenceJar. Seems like I should just bind the SDK AAR directly (with no added Java wrapper layer). I am rethinking this and trying to just create the binding assembly pointed to the SDK AAR in the JARS folder, and then include Google Play Services using NuGet.

继续,(使用 NuGet 引用 Google Play 服务)我现在收到此错误:<代码>找不到与给定名称匹配的资源(在值"处,值为@integer/google_play_services_version").{项目名称} {项目路径}\AndroidManifest.xml我尝试了很多不同的方法来试图摆脱这个构建时错误,但没有任何运气.

Proceeding with that, (using NuGet to reference Google Play Services) I'm now getting this error: No resource found that matches the given name (at 'value' with value '@integer/google_play_services_version'). {project name} {project path}\AndroidManifest.xml I've tried a LOT of different things to try to get rid of this build-time error, but have not had any luck.

如果我坚持使用 Google 的play-services-6.5.87.AAR"中的 JAR 文件作为嵌入式资源 Jar,我不会收到构建错误,但会收到 SDK 无法处理的运行时错误找到所需的 Android 清单设置.如果您有这样安排的项目,我是否正确使用了哪个 Android Manifest?<代码>XXX PCL 项目-->XXX.Android 项目 <-- 我猜这是将使用的 AndroidManifest.XML 文件所在的位置......?---->XXX.Android.AARBinding 项目
------>JARS 文件夹 -->3pVendorSDK.AAR

If I stick with using the JAR file from inside Google's 'play-services-6.5.87.AAR' as an embeddedResourceJar, I don't get the build errors, but I do get runtime errors that the SDK can't find Android manifest settings needed. If you have a project arranged like this, am I correct as to which Android Manifest is used? 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

还在挖掘中......

Still digging....

推荐答案

我是如何最终让我的 3rd Party Java SDK 与 Xamarin 一起工作的:

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

How I finally got my 3rd Party Java SDK to work with Xamarin:

Since my solution is to be Cross-Platform, I have:

  • 程序集:MyApplication(PCL 便携式)
  • 程序集:MyApplication.Android
  • 程序集:MyApplication.Android.Binding

    (包装第 3 方 SDK,以 AAR 文件形式提供)

相应的 .IOS 项目/程序集将遵循此命名模式,当我们到达时.

The respective .IOS projects/assemblies will follow this naming pattern, when we get to that.

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

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

    参考资料

    • 添加对 Android 绑定程序集的引用.

    组件 (NuGet)

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

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

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

    资产

    • 我的第 3 方 SDK 使用了 config.JSON 文件,需要将其放在这里,以便在运行时可以读取它.
      使用构建操作设置:'AndroidAsset'

    构建时间 需要额外的工作:

    Build Time Additional work needed:

    • 绑定程序集中的其他 MetaData.XML 更改.
      - 当编译的绑定程序集被 Android 程序集引用并尝试构建时,一些生成的代码具有 构建错误.
    • 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 代码转换构建错误,关于特定类的范围未达到预期/要求.为了解决这个问题,我回到 Binding 程序集的 MetaData.xml 文件并选择从生成的 Java 代码接口中删除问题类,因为我没有计划调用或使用.

    As stated above, when I built MyApplication.Android.Binding, it built fine on its own. When I referenced it in MyApplication.Android, though, it generated a new Java code translation build error about the scope of a particular class not being as expected/required. To address this, I went back to the Binding assembly’s MetaData.xml file and chose to remove the problem class from the generated Java code interface since I did not have plans to call or use.

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

    TIP: The easiest way to do this (that I've found) in Visual Studio is to enable the Show All Files feature on the BindingAssembly project, and then look in the obj\Debug\generated\src\ folders for the problem class. Once you find it, click on it and the generated Java interface code has the XPath statements generated as comments. These are what you need to either alter or remove the problem classes or methods using the MetaData.XML file.

    现在我需要做的就是在上面编写我的跨平台代码(使用 Dependency Inversion + Xamarin Forms 内置 DependencyService 在运行时访问每个 SDK),我的应用程序应该可以正常运行了!

    Now all I need to do is write my cross-platform code on top (using Dependency Inversion + Xamarin Forms built-in DependencyService to reach each SDK at runtime) and my app should be good to go!

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

    Hopefully these findings are helpful to others who need to work through a similar binding scenario.

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

    If you do see any content here that is incorrect, or if you have anything you'd like to add, please comment!

    这篇关于Xamarin.Android 绑定到具有依赖项的 3rd 方 SDK的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆