Sunday, December 15, 2013

Xamarin Mobile Development: Consuming Java Libraries from C# in Xamarin.Android - Part 2

On a previous blog post on Xamarin mobile app development and Android, we talked about how third-party libraries help to significantly cut down on the mobile development time by allowing app developers to not worry about building certain things, like a custom UI control or a client service. We also learned about binding and converting as well as what sort of things we should consider before getting started, like having a proper Java decompiler ready.


With all of these things set up and ready to go we can dive deep in some work!


 


We start by creating a new Android Java Bindings project


 


After Xamarin creates and loads the project, your Solution Explorer will have this content:


 


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 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 Build Action to EmbeddedJar. If the Jar is 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).


After doing that, if you build the project (F8) you'll receive 12 errors. But don't worry, this is a typical process when you're binding a native library.


 


As I previously pointed out, you'll touch the Transform files to fix binding issues.


Unfortunately, in the Xamarin documentation there is not too much information about how to fix these kind of errors.


I strongly recommend that you use a reflection/decompiler program like JD-GUI to inspect which objects are causing trouble, then load the jar assembly.


The first thing you will see is the namespaces composed. Let's start by detecting and fixing those errors.

1.  The type or namespace 'IUserAuthentication' does not exist in the namespace (Org.Jivesoftware.Smack)

Let's use reflection and navigate until that we get to that namespace.


 


Did you realize that there is no IUserAuthentication interface? That’s because C# linking uses conventions for the interfaces by adding the letter “I” at the beginning. So we need to specify in Metadata.xml file which is the correct name of the interface.

public

Note that you have to specify the original name of the assembly. Sometimes you can deduce it but in another time wouldn’t work that way. 

2. Inconsistent accessibility: base class 'Org.Jivesoftware.Smack.Util.Collections.AbstractHashedMap.EntrySet' is less accessible than class 'Org.Jivesoftware.Smack.Util.Collections.AbstractReferenceMap.ReferenceEntrySet'

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

    public-->    public    public    public    public    public    public

3. Now, if we build the solution we're going to receive more errors.


We might continue solving these errors. But as you notice, more errors are appearing than we are fixing. You could end up fixing more than 1000 issues. “Hey Xamarin, are you out of your mind?” maybe if you read very well the purposes of Transforms folders, I add this one: To customize the API design by changing names or types, by removing unused pieces, etc.


So I recommend just using those API’s or functions you do need in your project. So you can omit removing namespaces in the binding library and of course they will be there but you cannot access them.


Reviewing the documentation of the library in the project, we really need the namespace org.jivesoftware.smack to create a socket communication for the chat. Then, we can remove the namespace that we do not need.

                                                        

4. Now, we build again


We only see only one error inside of the namespace we're interested in.


'Org.Xmlpull.Mxp1.MXParser' does not implement interface member 'Org.XmlPull.V1.IXmlPullParser.EventType'. 'Org.Xmlpull.Mxp1.MXParser.EventType' cannot implement 'Org.XmlPull.V1.IXmlPullParser.EventType' because it does not have the matching return type of 'Org.XmlPull.V1.XmlPullParserNode'.

        Org.XmlPull.V1.XmlPullParserNode     

5. At the end, we will get more errors but just a few of them. The result is this.


Now, build the project and you’re ready to consume the data on an Android Project.


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


 


Now, try to access one class of the assembly in the activity.


 


You’ll see it is available to utilize the logic into your target project.


I know it can get tedious to see so many errors the first time. But at the end it is more reliable by utilizing third party libraries which use standards and have been tested by many users or when there's no .NET assembly to consume directly in your project.


Happy Decompiling :)


Oscar Fimbres is a Computer Science student. He has been involved in ASP.NET MVC and Windows RT projects. He currently works as Xamarin Mobile Developer at iTexico. Also he is a Microsoft Student Partner since 2011 spreading the word about Microsoft Technologies.


Contact Us


View the original article here

No comments:

Post a Comment