How to pass an interface to Java from Unity code?

First, let me say that this is my first experience with Unity, so the answer may be right under my nose.

I’m trying to create a plugin that allows me to access an SDK from my game. I can call SDK methods just fine using AndroidJavaObject and I can pass data to them with no issue. But there are some SDK methods that require an interface to be passed.

For example, my Java function:

public void attemptLogin(String username, String password, LoginListener listener);

Where listener is a callback interface. I would normally run this code from Java as such:

attemptLogin("username", "password", new LoginListener() {
    @Override
    public void onSuccess() {
        //Yay! do some stuff in the game
    }

    @Override
    public void onFailure(int error) {
        //Uh oh, find out what happened based on error
    }
});

Is there a way to pass a C# interface through JNI to my attemptLogin function? Or is there a way to create a mimic-ing interface in C# that I can call from inside the Java code (and pass in any kind of parameter)?

Thanks in advance! :slight_smile:

The documentation for AndroidJavaProxy is a bit lacking, but it’s possible to figure out the usage for this class.

As mentioned in the documentation, the class can be used “to implement any java interface”.

During its construction, you pass in a string that identifies the Java interface you’d like this instance to proxy, for example:

// Assuming com.example.TestInterface is a Java interface
AndroidJavaProxy proxy = new AndroidJavaProxy("com.example.TestInterface");

The AndroidJavaProxy class has a virtual Invoke method, that according to the documentation:

Called by the java vm whenever a
method is invoked on the java proxy
interface. You can override this to
run special code on method invokation,
or you can leave the implementation as
is, and leave the default behavior
which is to look for c# methods
matching the signature of the java
method.

A typical usage scenario would be subclassing AndroidJavaProxy, and defining a method that matches the Java interface method you’d like to be called:

public class LoginListener
{
    // TODO: replace with full Java name for LoginListener interface
    public LoginListener() : base("com.package.LoginListener")
    {
    }

    public void onSuccess()
    {
    }

    public void onFailure(int error)
    {
    }
}

Then you’d instantiate this class, and pass it to the Java method that accepts the interface type (shown in pseudo-code since i am not familiar with the exact details):

LoginListener listener = new LoginListener();

// Get AndroidJavaObject to call attemptLogin()
AndroidJavaObject obj = ....

obj.Call("attemptLogin", "user", "pwd", listener);

The default Invoke() method from AndroidJavaProxy should look for methods with the same name (and parameters) from the Java interface and call those on the C# class. If you’d like some other logic you can of course override the Invoke() method and provide some different logic.

There is no such way, AFAIK. You’ll have to use UnitySendMessage, which is a method of the UnityPlayer class. On my machine, that class lives inside /Applications/Unity4.3/Unity.app/Contents/PlaybackEngines/AndroidDevelopmentPlayer/bin/classes.jar . Note that it’s very limited - it can only pass one string as a parameter. So perhaps you’ll have to get creative.