Xamarin.Android Binding to 3rd party SDK with dependencies

泄露秘密 提交于 2019-12-03 15:34:31

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

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

  • Assembly: MyApplication (PCL Portable)
  • Assembly: MyApplication.Android
  • Assembly: MyApplication.Android.Binding

    (Wrapping the 3rd party SDK, provided as an AAR file)

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

Android Binding Assembly

  • 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.
    • I had some methods that returned types that did not map well to .Net, so I used attr elements to adjust their 'managedType' and 'managedReturn' type values.
      Note: You can use more than one attr element on one method to get it tweaked as desired.
    • I had to remove a method (by using a remove-node element) that was declared as virtual and re-add it in custom code as an override to satisfy the abstract class definition of its base class.
  • 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 Assembly

  • Manifest

    • Lacked accurate/complete SDK Manifest documentation.
      The Sdk manifest info changes were made here in the Android Assembly.
  • References

    • Add a reference to the Android Binding Assembly.
  • Components (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.Basement
    • Xamarin.GooglePlayServices.Gcm (the one added via VS Manage NuGet)
    • Xamarin.GooglePlayServices.Iid
    • Xamarin.GooglePlayServices.Tasks
  • Assets

    • 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’
  • Build Time Additional work needed:

    • 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.

Assembly Binding Transforms

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.

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.

Wrap-Up

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!

You should be able to do #3 which you simply reference the pre-built NuGet packages of these existing bindings of GPS/support libraries.

Please make sure that you use the exact version the binding library expects as google moves classes all the time.

My personal recommendation is the following in order of difficulty (easy -> hard):

  1. NuGet Package
  2. EmbeddedReferenceJar / ReferenceJar of the .jar or classes.jar (Use a LibraryProjectZip if there are resoruces)
  3. Binding projects for each dependency

As a best practice, yes you should use <remove-node> on items that you will not use. However this is mainly used when errors are being generated by code you won't use in the first place. I would just keep the items around regardless here unless there are quite a bit of methods you will never touch so you can be mindful of your dexcount.

For further help you can view my bindings guide: https://gist.github.com/JonDouglas/dda6d8ace7d071b0e8cb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!