Introduction of dotnet-binding-util

Introduction of dotnet-binding-util

You might have created a .NET binding library by yourself by following the guide Binding a Java library from Microsoft docs. In many cases, it’s quite simple and straight forward for small libraries. However, there few drawbacks:

  • 1/ You normally embed the native libraries artifacts inside your DLL

    • 1.a/ This makes your DLL is potentially very large

    • 1.b/ It might causes conflicts if two different Nuget packages embed the same libraries

    • 1.c/ We cannot utilize if the native libraries are already downloaded by Android Studio or other Android development tools.

  • 2/ You might try out Xamarin.Build.Download to download the libraries for you

    • The good point: We can get rid of item 1.a

    • Items 1.b & 1.c still persist

Other than that, a library normally doesn’t come without dependencies, we will have to analyze ourselves to find out

  • if there is a NuGet available out there

  • if not, we will need to create the binding ourselves

The things even get more headache when the libraries are privately distributed and protected with credentials on Gradle repositories.

By creating a lot of binding libraries (many are very big ones like Mapbox, Stripe, etc), I found the way that we can

  • Utilize Gradle - the native tool to manage Android/Java libraries either without credentials or with credentials, to download the libraries for us and a.

  • Find out the dependencies easily by reading POM files

  • Find out which dependencies are already bound with public NuGet packages

  • Upgrade version easily

In this series of Creating binding libraries for .NET Android, I will go through things step by step of how to use my approach for your own binding libraries based on my repository tuyen-vuduc/dotnet-binding-utils. At the end, you will get NuGet package(s) to use in your .NET Android app.

What do we have in this repository

1/ It is a toolset to create an .NET Android(Java) binding library

  • It will analyze all dependencies of the targeting binding library by reading POM files downloaded by Gradle

  • It will generate .NET Android (Java) binding library project(s) with appropriate dependencies

  • It will build and pack the final result in NuGet packages

2/ It manages metadata of many .NET Android(Java) binding libraries

  • Any Android (Java) binding libraries available on Nuget.org can have its metadata defined in this repo

  • Based on available metadata, it will link the corresponding NuGet packages of the dependencies to the generated CSPROJ file

    • If a NuGet is available without its metadata,

      • 1/ We need to add a new one similar to existing ones

      • 2/ Then run the tool again

    • If not available, then a binding library project will be generated

3/ It has several scripts to simplify binding error fixes

// process_field(); // generate metadata to change fields’ managed names to avoid name conflicts.
// process_IJsonDeserializer(); // genereate xpath for classes inherits from IJsonDeserializer
// process_Com_Example_Dsroom_Dao_IBaseDao();
// process_Com_Google_Android_Material_Circularreveal_ICircularRevealWidget();
// process_Android_Util_ITypeEvaluator();
// process_Android_Util_Property();
// process_downgrade();

Here are typical steps to create a new binding library

1/ Fork my repository

2/ Open Git Bash on Windows or Terminal on other systems

3/ Ensure the existing metadata up to date by running sh fetch.sh

4/ Find the library Gradle details

  • The Gradle implementation of the library e.g. de.hdodenhof:circleimageview:3.1.0

  • The Gradle repository details

    • URL

    • Credentials

  • By default, only these public repositories are supported

    • Maven Central

    • Google

    • JCenter

5/ Create the binding libraries by running sh bind.sh —artifact {YOUR_BINDIDNG_LIBRARY_IMPLEMETNATION_SYNTAX_IN_GRADLE}

6/ Fix all binding errors as reported then do the step 5 again until no more errors reported

7/ Create a PR to merge your changes to the main repository

If you’re lucky, you won’t have to do step 6 where no errors reported, there will be NuGet packages generated in nugets folder. Otherwise, you need to be patient and careful to fix all reported errors then do step 7 as the final step.

With generated NuGet packages, you can consume them locally or distribute wherever you prefer.

Let’s create a binding library

In this simple demonstration, let’s create the binding library for de.hdodenhof:circleimageview:3.1.0 as mentioned the guide from Microsoft referred early in this post.

1/ Fork the library

Please do the fork then clone to your local machine if you haven’t.

2/ Open bash based terminal

  • Open the repository in Visual Studio Code

  • Open bash based terminal panel as well

    • On Windows, I normally use Git Bash which is installed along with Git for Windows.

3/ Ensure the metadata up-to-date

I created a simple XUnit test to fetch the metadata of the existing libraries defined in the repository easily.

To invoke the update process, simply run sh fetch.sh on your preferred bash based terminal.

On Windows, I recommend use Git Bash which comes along when you install Git for Windows.

As you can see, after running the script, there are many libraries updated either a new patch or even a new version.

Commit these changes before moving onward.

4/ Find the library’s Gradle details

After searching circleimageview on Google Search, we can see its GitHub repository

By checking out the README, we can easily find out the Gradle implementation of the library.

dependencies {
    ...
    implementation 'de.hdodenhof:circleimageview:3.1.0'
}

What we need is the value of de.hdodenhof:circleimageview:3.1.0

NOTE: Android/Libraries are normally distributed on Maven Central repository which is similar to NuGet.org in .NET world. You can search for the libraries there as well to easily get their latest versions if not presented in the README.

5/ Create the binding library

Creating a binding library normally requires many steps, but I created a script, bind.sh, to make our life easier. Executing it will

  • Create the binding library project for the targeted library

  • Add NuGet packages for all dependencies having corresponding metadata

  • Add and link binding projects for dependencies without corresponding metadata

The syntax is

# sh bind.sh —artifact {ARTIFACT_GROUP}:{ARTIFACT_NAME}:{VERSION}
sh bind.sh —artifact de.hdodenhof:circleimageview:3.1.0

Here is what you can see when executing sh bind.sh —artifact de.hdodenhof:circleimageview:3.1.0

  • It’s starting

  • It’s successfully without any binding errors

As you can see on the right left hand side, a binding project is created with all required files which are for fixing binding errors.

6/ Fix reported binding errors

As you can see, no errors are reported, then we can skip this step.

The process of fixing binding errors sometimes is very simple, but sometimes is very complex; however, we need to always follow the guide from Microsoft as the base line.

7/ Create the PR to merge your new binding library to my repository

Commit all the changes then create the PR.

Please follow the guide from GitHub to complete this step.

We can skip if for now and check out the generated library packed as a NuGet library first.

You can use it locally or upload it to NuGet.org then use. If you prefer a local try first, you can check out this guide if you don’t know yet.

Wraps up

In this post, I introduced you my repository dotnet-binding-utils which is to utilize Gradle and other custom scripts to simplify the process of creating an Android binding library. The major benefits are

  • Utilize the native Android package management to manage Android dependencies

  • Reduce diskspace if we work on both Android native development and .NET Android development

  • Simple process

  • Results consumed easily as NuGet packages

I hope it will help and benefit you guys.

It’s just the start, there are many other scenarios, please check out my other related posts (upcoming).

Happy coding!!!

NOTE: Microsoft also introduced a new way of adding a native Android library which is publicly available on Maven Central library. What I don’t like is it doesn’t utilize Gradle but Xamarin.Build.Download to download the dependency.