Consuming Android Libraries from C# For Xamarin Development

The third-party library ecosystem for Android is massive. Because of this, it frequently makes sense to use an existing Android library than to create a new one. Xamarin.Android offers two ways to use these libraries:

  • Create a Bindings Library that automatically wraps the library with C# wrappers so you can invoke Java code via C# calls.
  • Use the Java Native Interface (JNI) to invoke calls in Java library code directly. JNI is a programming framework that enables Java code to call and be called by native applications or libraries.

Xamarin.Android implements bindings by using Managed Callable Wrappers (MCW). MCW is a JNI bridge that is used when managed code needs to invoke Java code.

Getting Started

We start by creating a new Android Java Bindings project and write a name for the project.

We can find the aar or jar file from maven or other similar web sites, or if we want to use the file from the cache of the Android Studio dependencies downloads.

Mac/Windows Path (~User/.grandle/caches/modules-2/files-2.1/PackageFolder)

I'm going to explain what each folder is for:

  • Additions: allows you to add C# arbitrarily to the generated classes before they are compiled. This can be helpful for providing convenience and extra functionality like new methods to have pure C# classes.
  • Jars: this is the jar files in which the bindings should be generated.
  • Transforms: usually, you will need to access to the transform files after the bindings project reads out all the information from the jar; so you've got to use these files to modify the library before it becomes an assembly. The reasons to interact with these files are:

              - To fix issues with the binding (very common)

              - To customize the API design by changing names or types, by removing unused pieces, etc.

Now, start by adding the jar or aar file into Jars folders. In this case we want to create link of this native code to C#, so in Properties Window you need to make sure to change the Build Action to EmbeddedJar for Jar file and LibraryProjectZip for aar file. If the jar or aar are only a dependency of another one and you don't necessarily need to link the code, you'll set EmbeddedReferenceJar (although this is not case).

We’re going to build our project and see all the error from the binding process, you'll touch the Transform files to fix binding issues.We can find some samples and troubleshooting in the Xamarin documentation. After doing that, if you build the project you'll receive 3 errors. But don't worry, this is a typical process when you're binding a native library.

When we talk about accessibility, we refer to modifiers. Change these classes to protected visibility.

<!-- Error CS0507: 'ShimmerFrameLayout.OnLayout(bool, int, int, int, int)': cannot change access modifiers when overriding 'protected' inherited member 'FrameLayout.OnLayout(bool, int, int, int, int)' -->

<attr path="/api/package[@name='com.facebook.shimmer']/class[@name='ShimmerFrameLayout']/method[@name='onLayout' and count(parameter)=5 and parameter[1][@type='boolean'] and parameter[2][@type='int'] and parameter[3][@type='int'] and parameter[4][@type='int'] and parameter[5][@type='int']]" name="visibility">protected</attr>

Metadata.xml


In some many times we can’t fix all the errors from the metadata, in this case we’ll use the Additions folder to implements the missing methods.

   public partial class Shimmer : global::Java.Lang.Object

   {

       public partial class AlphaHighlightBuilder : global::Facebook.Shimmer.Shimmer.Builder

       {

           // Error CS0534: 'Shimmer.AlphaHighlightBuilder' does not implement inherited abstract member 'Shimmer.Builder.RawThis.get'

           protected override Java.Lang.Object RawThis

           {

               get

               {

                   return new Java.Lang.Object(JNIEnv.CallObjectMethod(Handle, JNIEnv.GetMethodID(JNIEnv.GetObjectClass(Handle), "getThis", "()Lcom/facebook/shimmer/Shimmer$Builder;")), JniHandleOwnership.TransferLocalRef);

               }

           }

       }


       public partial class ColorHighlightBuilder : global::Facebook.Shimmer.Shimmer.Builder

       {

           // Error CS0534: 'Shimmer.AlphaHighlightBuilder' does not implement inherited abstract member 'Shimmer.Builder.RawThis.get'

           protected override Java.Lang.Object RawThis

           {

               get

               {

                   return new Java.Lang.Object(JNIEnv.CallObjectMethod(Handle, JNIEnv.GetMethodID(JNIEnv.GetObjectClass(Handle), "getThis", "()Lcom/facebook/shimmer/Shimmer$Builder;")), JniHandleOwnership.TransferLocalRef);

               }

           }

       }

   }

Shimmer.cs


Our solution looks like this.

 

Referencing the Binding Library

Create your target project to consume the assembly and tap contextual menu on References folder. Click Edit References and check it.

 

We’re going to modify the necessary elements to work with our binding, in this case we’re going to edit the layout to create our custom view.

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">

   <com.facebook.shimmer.ShimmerFrameLayout

     android:id="@+id/shimmer_view_container"

     android:layout_width="wrap_content"

     android:layout_height="wrap_content"

     android:layout_gravity="center"

     app:shimmer_duration="1000">

   <LinearLayout

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

       android:gravity="center"

       android:orientation="vertical">

     <ImageView

         android:layout_width="64dp"

         android:layout_height="64dp"

         android:src="@mipmap/ic_launcher"/>

     <TextView

         android:layout_width="wrap_content"

         android:layout_height="wrap_content"

         android:layout_marginTop="20dp"

         android:gravity="center"

         android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."/>

   </LinearLayout>

 </com.facebook.shimmer.ShimmerFrameLayout>

</RelativeLayout>

activity_main.axml

 

On our MainActivity we’re going to run the animation on the lifecycle of the activity.

      private ShimmerFrameLayout shimmerViewContainer;


       protected override void OnCreate(Bundle savedInstanceState)

       {

           base.OnCreate(savedInstanceState);

           SetContentView(Resource.Layout.activity_main);

           shimmerViewContainer = FindViewById<ShimmerFrameLayout>(Resource.Id.shimmer_view_container);

       }


       protected override void OnResume()

       {

           base.OnResume();

           shimmerViewContainer.StartShimmer();

       }



       protected override void OnPause()

       {

           shimmerViewContainer.StopShimmer();

           base.OnPause();

       }

MainAcitivity.cs

 

Run the Sample App

 

About the Author

Josue Diaz is a Computer Electronics Engineer with 2+ years of experience in Xamarin Development.  He's creating Android and iOS apps here at iTexico.

Meet with Lance V. Director of Mobile Practice

Lance can walk you through how to integrate your mobile strategy into your business seamlessly.

Lance Mobile CC

You may also like:

Post Your Comment Here