Xamarin Bindings

In order to use Batch with Xamarin, you will need to generate binding projects.

Getting started

First of all, install a copy of Xamarin (or Visual Studio for Mac) which supports at least Android 8.0 and iOS 11. To generate the iOS binding, you'll also need Xcode 9 or higher.

Since we'll start from scratch, create a new Xamarin.Forms "Blank Forms App" project. You can name it however you want: we'll use "BatchDemo" for this tutorial.
These instructions are written for Visual Studio Community for Mac, so your experience might differ a little if you're using Visual Studio on Windows.

You should end up with a solution that has three projects:

  • BatchDemo
  • BatchDemo.Droid
  • BatchDemo.iOS

Lets build the bindings!

Android

Generating the base Android binding project

Note: Batch versions lower than 1.10.1 are not supported by this tutorial

First, get Batch's AAR on our download page .
Then, follow Xamarin's AAR binding tutorial using that AAR, right until "Accessing .AAR types".

Rather than making a new solution, add the binding project to the current solution by right clicking it, and selecting "Add > Add New Project".
We'll call the project BatchSDK.Android.

You should end up with a binding project referenced by your Android Xamarin Forms project.
It will have several errors and warnings on compilation, which we'll fix by tweaking how Xamarin generates the bindings.

Fixing the build issues

From the Transforms folder, open Metadata.xml, and replace it with this:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>

    <!-- CS0109 should be ignored: https://bugzilla.xamarin.com/show_bug.cgi?id=58932 -->

	<!-- CS0618 should also be, since we internally use deprecated stuff for compatiblity -->
	
    <attr path="/api/package[@name='com.batch.android']" 
        name="managedName">BatchSDK.Android</attr>
	
	<attr path="/api/package[@name='com.batch.android']/
        interface[@name='BatchInboxFetcher.OnNewNotificationsFetchedListener']/method[@name='onFetchSuccess']"
        name="argsType">FetchNewNotificationsSuccessEventArgs</attr>

    <attr path="/api/package[@name='com.batch.android']/
        interface[@name='BatchInboxFetcher.OnNewNotificationsFetchedListener']/method[@name='onFetchFailure']"
        name="argsType">FetchNewNotificationsFailureEventArgs</attr>

    <attr path="/api/package[@name='com.batch.android']/
        interface[@name='BatchInboxFetcher.OnNextPageFetchedListener']/method[@name='onFetchSuccess']"
        name="argsType">FetchNextPageSuccessEventArgs</attr>

    <attr path="/api/package[@name='com.batch.android']/
        interface[@name='BatchInboxFetcher.OnNextPageFetchedListener']/method[@name='onFetchFailure']"
        name="argsType">FetchNextPageFailureEventArgs</attr>

    <remove-node path="/api/package[@name='com.batch.android']/class[@name='Config']/field" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='BatchUserProfile']/method[@name='a']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='BatchUserProfile']/method[@name='b']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='BatchUserProfile']/method[@name='c']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='h']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='BatchPushReceiver']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='Batch']/method[@name='a']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='Batch']/method[@name='b']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='Batch']/method[@name='c']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='BatchPushPayload']/method[@name='a']" />
   
	<remove-node path="/api/package[contains(@name, 'com.batch.android.') and not(contains(@name, 'com.batch.android.json'))]" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='h.1']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='MessagingActivity.1']" />

	<remove-node path="/api/package[@name='com.batch.android']/class[@name='BatchInboxNotificationContent']/constructor[@name='BatchInboxNotificationContent']" />
	
</metadata>

Then, we need to ignore some warnings for the whole project:

To do so, open BatchSDK.Android's options, go to Build > Compiler, and write CS0109,CS0618 in Ignore warnings.

Build the solution: everything should build without errors or warnings. If not, feel free to contact out support team!

Batch's Android APIs will now be available under BatchSDK.Android once you add that project to your existing solution and reference it.
Note that you will still need to follow our Android documentation, including adding the Play Services library (with it's gcm and instanceid components) and required entries to your manifest.

iOS

Creating the base iOS binding project

Note: Batch versions lower than 1.10.3 are not supported by this tutorial

First, create a new iOS Bindings Library project in your solution, which we will call BatchSDK.iOS. Reference it from your Xamarin forms iOS project.

Then, get Batch's framework binary from our download page , and copy Batch.framework from the Batch.embeddedframework in your BatchSDK.iOS project, folder.
Your folder hierarchy should look like that:

iOS Project Structure

Right click on Native References in Visual Studio for Mac, select Add Native Reference and pick Batch.framework.
Finally, select ApiDefinition.cs and Structs.cs, right click and select Remove. When asked, select Delete: these are unneeded files that we're gonna generate with objective sharpie.

We're now ready to go ahead and geneate the actual bindings with Objective Sharpie.

Using Objective Sharpie

Download and install Objective Sharpie from Xamarin's website.

Then, open a terminal in the BatchSDK.iOS folder and run the following command:

sharpie bind -output . -namespace=BatchSDK.iOS -sdk=iphoneos Batch.framework/Headers/*.h

Go back to Visual Studio for Mac, right click on the project, and select Add Files.
Pick the newly generated ApiDefinitions.cs and StructsAndEnums.cs from the project directory, and confirm.

For both files, you will need to change the build action.
Right click on them, and under Build Action, select:

  • ObjcBindingApiDefinition for ApiDefinitions.cs
  • ObjcBindingCorseSource for StructsAndEnums.cs

iOS Build Action

The project will still not build correctly: we'll need to patch the API definitions.

Patching the API definitions

Since Objective Sharpie is imperfect, a couple of patches are required to the generated files to build the bindings.

In both files:

  • Search for [iOS (8, 0)] (or [iOS (8,0)]) and replace with [Introduced (PlatformName.iOS, 8, 0)]
    Do the same for any version variation.

In ApiDefinitions.cs:

  • Remove using Batch;
  • Search for every interface extending an intefrace starting with IBatch...., and remove the I. Objective Sharpies does not consistently names the interfaces. For example, interface BatchManualUserActionSource : IBatchUserActionSource becomes interface BatchManualUserActionSource : BatchUserActionSource
    Building the solution and looking at the errors might help you find these problems.
  • Look for anything annotated with Verify. You'll need to remove those, and fix the definition accordingly.
    Here are a couple of known fixes:

    • BatchMessage PopPendingMessage { get; } -> BatchMessage PopPendingMessage();
    • bool ShowPendingMessage { get; } -> bool ShowPendingMessage();
    • BatchInboxFetcher Fetcher { get; } -> BatchInboxFetcher Fetcher();
    • BatchUserDataEditor Editor { get; } -> BatchUserDataEditor Editor();
  • The following definitions are correct, and just need their Verify removed:

    • bool IsRunningInDevelopmentMode { get; }
    • BatchUserProfile DefaultUserProfile { get; }
    • string LastKnownPushToken { get; }
    • string InstallationID { get; }

In StructsAndEnums.cs:

  • Replace nuint occurrences on enums with ulong.
  • Replace any enum with the Native attribute's type to long, except ones that were of nuint type.

The project should now build correctly.