My Experience Writing a Xamarin Binding Project

Xamarin is a tool and platform for developing cross platform mobile applications. The company I work at (mParticle) enables developers to send data to many analytics services by integrating our SDK once instead of an SDK for each of those analytics services. Not only does this save time and money, developers also love it. In the spirit delighting developers, we decided to write a Xamarin SDK for our service. The purpose of this post is just to share my experience and some technical tidbits I think are useful. (There are plenty of more detailed tutorials on bindings so I won’t dive too deep.)

Start from scratch or binding?

If your SDK doesn’t access any native functionality (or very little of it), you’re probably better of just creating a PCL A PCL will also giving you more flexibility for other platforms beyond the standard iOS, Android and UWP.

In our case, since we rely on a lot of the underlying native API (for instance around install tracking), we decided to go with the binding approach.

Project Structure

  • Bindings — where the native bindings project live
  • Library — where the simplified API lives
  • Samples — Contains both Native and Forms samples that use the SDK

Android Binding

Bindings rarely work on the first try. Thankfully, Xamarin has improved quite a bit since the early days. Fixing the binding project essentially involves editing a file in your binding project call Metadata.xml. It helps you control the C#output of the binding generator. Majority of the fixes include simply removing classes/packages from the C#API since we only wanted to expose the commonly used public API. Other fixes include changing the visibility of a method or renaming field and parameter names. See here for examples.

We did have some issues using the Java doc to C# docs feature which is essentially suppose to generate nice XML summary comments and name the method parameters correctly. Ultimately, we didn’t need this since we would be calling our binding project from another C# project so we could (and did) just added XML there. More on that later.

iOS Binding

https://developer.xamarin.com/guides/cross-platform/macios/binding/objective-sharpie/getting-started/

Then, create a new Xamarin iOS binding project. You’ll need to copy whatever C# code was generated from the ObjectiveSharpie command into the corresponding C# files in the project. You may need to fiddle with it a little bit since the ObjectiveSharpie generated code may be missing a namespace. Similar to Android, the bindings generator is not perfect. iOS is however a little bit easier since you can just edit the ApiDefinition.cs C# file directly (instead of an XML file).

The most common fix we had to do was adding [Protocol] to some classes. Visual Studio for Mac will incorrectly show compile errors so first try and actually build the binding project. Also, be careful if your library is using reflection to detect and use another library (as we do for our optional kits). You may have to disable SmartLink on that particular dependency library.

Writing a Cross Platform API

Here’s Android

MParticle.Android.Instance.LogEvent (
"Hello world",
AndroidEventType.Navigation
);

and iOS

MParticle.iOS.Instance.logEvent (
new NSString("Hello world"),
iOSEventType.Navigation
);

The point is exaggerated a bit here but essentially the method names differed and so did the datatypes. One of the biggest advantages of Xamarin is code sharing which means you can write code once and share it among multiple projects (or in this case platforms). So we felt we could improve on this and essentially allow users to make a single call like this for both Android and iOS

MParticle.Instance.LogEvent (
"Hello world",
EventType.Navigation,
);

To achieve this, we had to write a platform-independent interface which would be implemented for each platform. We also used a “bait-and-switch” PCL technique as outlined here. Using this technique meant we could deploy a single NuGet package instead of one for each platform.

Other Tips

  • Turn on the most verbose logging output to see exactly what is going.
  • Test your library on both an emulator/simulator and real device.
  • If the sample iOS app with your SDK runs on Simulator but not on the device (or vice versa), check to make sure your native library has all the required architecture slices (x86_64, i386, etc.)
  • Be sure to include all dependent frameworks (like UIKit, SystemConfiguration, etc) when including your native library.
  • You can debug the native Android library easily if you have the source code and then attaching to the process in Android studio
  • You can also debug the native iOS library but you need to make sure optimization is turned off for the framework/static library.
  • Google thoroughly for your issues but if you’re absolutely stuck, ask for help. There’s a very active and responsive community on StackOverflow (as long you attach the right tags or use the right description) and there is also a slack channel which has some active members.

Final Thoughts

Creating the nuspec file for our NuGet was mostly a manual process. I wish I had Googled earlier/harder for it but it looks like there was a Visual Studio template for it. Perhaps, it should be a default template in Visual Studio for Mac.

Credit and References

Oh and by the way, if you liked this project or what we’re doing at mParticle, check out our hiring page here as we have lots of positions. Reference this blog post if you like.

If you find any issues or mistakes in this posting, comment below and I’ll fix them as soon as possible.