Xamarin Android binding does not implement interface issue

1.6k Views Asked by At

I've a java binding for android which somewhat works bar the new feature I'm trying to integrate with. Only now I have realised that the intended callback is not happening. Here are the classes (decompiled to java) in question:

At the top level we have

public interface MyPackage {
   MyPackage.Companion Companion = MyPackage.Companion.$$INSTANCE;

public static final class Companion {
      @Nullable
      private static MyEventHandler myEventHandler;
      // $FF: synthetic field
      static final MyPackage.Companion $$INSTANCE;

      @Nullable
      public final MyEventHandler getMyEventHandler() {
         return myEventHandler;
      }

      public final void setMyEventHandler(@Nullable MyEventHandler var1) {
         myEventHandler = var1;
      }

      private Companion() {
      }

      static {
         MyPackage.Companion var0 = new MyPackage.Companion();
         $$INSTANCE = var0;
      }
   }
}

MyEventHandler class:

public abstract class MyEventHandler {
   public abstract void handleEvent(@NotNull String var1, @NotNull Properties var2);
}

Properties class:

import java.util.Map;

public class Properties extends r {
    public Properties() {
    }

    Properties(Map<String, Object> var1) {
        super(var1);
    }

    public Properties a(String var1, Object var2) {
        super.b(var1, var2);
        return this;
    }
}

and the problematic r class:

public class r implements Map<String, Object> {
    private final Map<String, Object> a;
various implementations...
}

So I noticed the issue when I couldnt override the HandleEvent method at the integration level and started looking at the Binding logs and found:

Warning=>

BINDINGSGENERATOR: Warning BG8801: Invalid parameter type MyPackage...Properties in method HandleEvent in managed type MyPackage.MyEventHandler. (BG8801)

And in build logs:

message BG0000: warning BG8102: Class MyPackage....Properties has unknown base type MyPackage....r.

warning BG8801: Invalid parameter type MyPackage...Properties in method HandleEvent in managed type MyPackage.MyEventHandler.

As it was obvious r is an obfuscated class I need to make chagnes to my Metadata so I went ahead and popped in:

<attr path="/api/package[@name='MyPackage']/class[@name='r']" name="obfuscated">false</attr>

Which resulted in the R being generated but now I get the 5 following compile error:

Error CS0535: 'R' does not implement interface member 'IMap.EntrySet()' (CS0535) 
Error CS0738: 'R' does not implement interface member 'IMap.KeySet()'. 'R.KeySet()' cannot implement 'IMap.KeySet()' because it does not have the matching return type of 'ICollection'. (CS0738)
Error CS0535: 'R' does not implement interface member 'IMap.Put(Object?, Object?)' (CS0535)
Error CS0535: 'R' does not implement interface member 'IMap.PutAll(IDictionary?)' (CS0535)
Error CS0738: 'R' does not implement interface member 'IMap.Values()'. 'R.Values()' cannot implement 'IMap.Values()' because it does not have the matching return type of 'ICollection'. (CS0738)

I tried to make a managed return using

<attr path="/api/package[@name='MyPackage']/class[@name='r']/method[@name='entrySet' and count(parameter)=0]" name="managedReturn">Java.Util.IMap</attr>

With same number of compile error as above. Then I tried removing the node using:

<remove-node path="/api/package[@name='MyPackage']/class[@name='r']/method[@name='entrySet']"/>

Still no luck. :(

What am I missing here? Any pointers/suggestions will be appreciated!

2

There are 2 best solutions below

0
On BEST ANSWER

I got arround fixing it by providing implementation of the the said methods in a partial class. Basically added a new file called R.cs under Additions folder as follows:

namespace YourNameSpace
{
    public partial class R
    {
        public void PutAll(System.Collections.IDictionary p0)
        {
            PutAll(p0);
        }

        public Java.Lang.Object Put(Java.Lang.Object key, Java.Lang.Object value)
        {
            return Put(key, value);
        }

        public System.Collections.ICollection EntrySet()
        {
            return EntrySet();
        }

        public System.Collections.ICollection KeySet()
        {
            return KeySet();
        }

        public System.Collections.ICollection Values()
        {
            return Values();
        }
    }
}

I couldn't get it to work by adding XML transformation, but I think there was some tooling issue.

2
On

It seems like you are trying to expose a Map to C# and as you stated, Java Generics are not handled very well.

In a very popular social network you received an answer from @mattleibow. I do not take credit for his answer but I went to check nonetheless and it seems fine.

If you look at the description of the Java.Lang.HashMap type https://learn.microsoft.com/en-us/dotnet/api/java.util.hashmap?view=xamarin-android-sdk-9 it's a good candidate for you to expose.

You can also try with the corresponding interface for better safety https://learn.microsoft.com/en-us/dotnet/api/java.util.imap?view=xamarin-android-sdk-9

If it works you will still have to cast the types yourself.

Please answer to the comment to say that problem is solved for the sake of future generations arriving on this post :D

Credit is not mine so don't give it to me :-)

John,