2 Comments

Exporting a Java Library to a Xamarin.Forms Android Project

The device on our current project has two unique software development kits (one for Android and one for iOS). My team wanted to use Xamarin.Forms to create an application for the device so that the core logic of the app could be stored in one place. 

However, in order to also incorporate the platform-specific SDK methods, we had to export Java code (for Android) and Swift code (for iOS) as libraries and then import those libraries into a Xamarin.Forms project.

In this post, I will go through the steps I used to import the functionality from Android into a Xamarin.Forms project. There are three main steps involved in the process:

  1. Generating an .AAR file in the Android Studio project. The .AAR file contains bundled Java classes, methods, and perhaps Android shared resources.
  2. Creating a Xamarin.Forms binding project that creates a bindings library (generated as a DLL) for the .AAR file. The DLL can be used by any Xamarin.Forms project. 
  3. Importing this DLL file and then use the functionality the library provides. I used the imported functionality to implement the Android version of a message interface.

Below is an example of exporting a Java class that stores hello and goodbye messages to a DLL that can then be used by a Xamarin.Forms project.

1. Create an .AAR File

Start by creating a new Android Studio project. In this example, mine is called MyApplication.

Next, create a new module (File -> New -> New Module -> Android Library).  I called mine myarr.

Now create a new package (right-click on Java, New -> Package -> in src/main). Use the name message so you’ll be able to access the contents of the package in Xamarin.Forms using the syntax message.{method}.

Inside of this package, create a class with functionality that you would like to export to Xamarin.Forms. I created a class called MyMessage with the ability to display two custom messages:


package message;
   public class MyMessage 
   {
      static String hello = "Hello dear user!";
      static String bye = "Bye for now. See you later!";
      public String helloMessage(){ return hello; }
      public String byeMessage() { return bye; }
   }

To build the .AAR file, right-click on your project name (in my case, messages), then click the Gradle tab on the far left of the screen. Go to Build -> Assemble Release. 

Your .AAR file will now be located at {project name}/{module name}/build/outputs/aar. For example, mine was located at MyApplication/myarr/build/outputs/aar.

2. Create a Bindings Library for the .AAR File

In this step, the goal is to use the .AAR file containing the compiled Java code to generate a DLL which can then be referenced in the Xamarin.Forms project.

Create a new solution in Xamarin.Forms. I called mine ExportAar.

Add the .AAR file to the Jars folder included in the template. Right-click on Jars, click Add -> Add Files, and copy the the .AAR file generated in Step 1. The .AAR file should now appear in the Jars folder.

Check to make sure the Build Action of the .AAR file is set to LibraryProjectZip by right-clicking on file -> Build Action -> Library Project Zip.

Build the project. The DLL file should be in {SolutionName}/bin/Debug/{SolutionName}.dll.

3. Use the DLL in a Xamarin.Forms Project

Finally, import the message-generating library in Xamarin.Forms and generate some messages.

Create a new Visual Studio project to use the library. I created a BlankForms App and called it ImportAar.

Next, we’ll import the DLL file created in Step 2 into the {ProjectName}.Droid. To do this, go to references -> Edit References -> .NetAssembly -> Browse. Find the DLL file generated in Step 2, click OK, and build.

The name of the imported .NET Assembly should now appear under references. To view the members of the imported project, double-click on the project name.

In order to test the library, I created an interface returning hello and goodbye messages and implemented the interface on Android and iOS (for now, iOS simply returns default values).


using System;
namespace ImportAar
{
    public interface IMessage
    {
        String helloMessage();
        String goodbyeMessage();
    }
}

To access the variables/methods of the imported .NET Assembly, create an instance of the imported class. The Android implementation of the iMessage interface creates an instance of MyMessage and calls the appropriate methods on it:


using System;
using ImportAar.Droid;
[assembly: Xamarin.Forms.Dependency(typeof(MyMessage))]
 
namespace ImportAar.Droid
{
    public class MyMessage : IMessage
    {
        public MyMessage() {}

        public String helloMessage(){
            Message.MyMessage message = new Message.MyMessage();
            String hello = message.HelloMessage();
            return hello;
        }

        public String goodbyeMessage(){
	    Message.MyMessage message = new Message.MyMessage();
            String bye = message.ByeMessage();
	    return bye;
        }

    }
}

Now that the interface returning messages has been implemented in Android, all we have to do is call it. I adjusted the blank forms project template by naming the default label myLabel.

I then used dependency service to call the correct implementation of the helloMessage for the platform I was on. This allowed me to call the Android implementation of the iMessage interface.


InitializeComponent();
IMessage platform = DependencyService.Get();
myLabel.Text = platform.helloMessage();

When I run the app in Xamarin.Forms, my Android phone displays the hello message specified in the MyMessage Java class created in Android Studio.