Nitha Paul
Nitha Paul

Reputation: 1401

Issue while creating Android binding for Xamarin

I am trying to create a binding project for a library that our organisation is already created. I have added the .aar file and when I try to build I am getting the below two error.

 Error JAVAC0000:  error: OnCompletionListenerImplementor is not abstract and does not override abstract method onCompletion(LockEvent,int,Metadata) in OnCompletionListener

public class OnCompletionListenerImplementor (JAVAC0000)

Error JAVAC0000:  error: SingleStepView_OnSelectionListenerImplementor is not abstract and does not override abstract method onSelected(Metadata,LockEvent) in OnSelectionListener
public class SingleStepView_OnSelectionListenerImplementor
 (JAVAC0000)

In the API.xaml

It is generated like this,

<interface abstract="true" deprecated="not deprecated" final="false" name="OnCompletionListener" static="false" visibility="public" jni-signature="Lno/zedoapp/zebra/key_ui/ui/listener/OnCompletionListener;"></interface>
<interface abstract="true" deprecated="not deprecated" final="false" name="SingleStepView.OnSelectionListener" static="true" visibility="public" jni-signature="Lno/zedoapp/zebra/key_ui/ui/view/SingleStepView$OnSelectionListener;"></interface>

Also I have noticed in Object browser that the class is not generating properly.

public interface IOnCompletionListener : IJavaObject, IDisposable, IJavaPeerable
{
}

internal sealed class IOnCompletionListenerImplementor : Java.Lang.Object, IOnCompletionListener, IJavaObject, IDisposable, IJavaPeerable
{
    public IOnCompletionListenerImplementor ()
        : base (JNIEnv.StartCreateInstance ("mono/Lno/zedoapp/zebra/key_ui/ui/listener/OnCompletionListenerImplementor", "()V"), JniHandleOwnership.TransferLocalRef);

    internal static bool __IsEmpty (IOnCompletionListenerImplementor value);
}


public interface IOnSelectionListener : IJavaObject, IDisposable, IJavaPeerable
{
}

internal sealed class IOnSelectionListenerImplementor : Java.Lang.Object, IOnSelectionListener, IJavaObject, IDisposable, IJavaPeerable
{
        public IOnSelectionListenerImplementor ()
            : base (JNIEnv.StartCreateInstance ("mono/Lno/zedoapp/zebra/key_ui/ui/view/SingleStepView_OnSelectionListenerImplementor", "()V"), JniHandleOwnership.TransferLocalRef);

        internal static bool __IsEmpty (IOnSelectionListenerImplementor value);
}

Can someone help me to interpret the issue and to solve my binding

Upvotes: 11

Views: 1159

Answers (1)

Breeno
Breeno

Reputation: 3156

The documentation at this link is somewhat misleading in my opinion.

It tells you that you need to give the generated EventArgs classes different names because the binding generator does not play well with generics and can't tell the different between the 2 Java interfaces. You do that by adding transform rules like the below to the Medata.xml file:

<attr path="/api/package[@name='com.whatever.android']/interface[@name='InterfaceListenerA']/method[@name='onJavaInterfaceMethodName']"
    name="argsType">InterfaceListenerAEventArgs</attr>

<attr path="/api/package[@name='com.whatever.android']/interface[@name='InterfaceListenerB']/method[@name='onJavaInterfaceMethodName']"
    name="argsType">InterfaceListenerBEventArgs</attr>

In my case this allowed my binding project to build. But when I tried to reference it in an Xamarin Android project and build it, I get the above error.

What the docs don't tell you is that when you do this the generated event name will mean that the code no longer implements the required interface in the generated java code. To make it do that you need to map the java interface method to the renamed C# event property name. To do that I added rules like these:

<attr path="/api/package[@name='com.whatever.android']/interface[@name='InterfaceListenerA']/method[@name='onJavaInterfaceMethodName']"
    name="managedName">InterfaceListenerA</attr>

<attr path="/api/package[@name='com.whatever.android']/interface[@name='InterfaceListenerB']/method[@name='onJavaInterfaceMethodName']"
    name="managedName">InterfaceListenerB</attr>

Note: The managed name is not necessarily the same as the Java interface name - it's whatever name you've given to each of the new EventArgs classes without the "EventArgs" suffix.

Upvotes: 5

Related Questions