- Home /
The question is answered, right answer was accepted
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! :)
in unity web player build, u just send a function to unityObject.js script using Application.ExternalCall( "$$anonymous$$yfunction" ,"0");
from this $$anonymous$$yfunction in unityobject.js script u can call java(may be java applet is best)
I once managed to access the Android platform with .dll interface. It was complicated but the important part of the process was having a Handle on the 'Context' and passing that along. Anyway, it may not be directly relevant to you but I recall that there were some good links in there that may be able to shed more light on things.
https://answers.unity.com/questions/1163907/how-can-i-detect-if-the-back-button-is-virtual-or.html
You may need to import or include the objects which contain the interface code if they are not otherwise somehow linked or accessible. For example, to get hold of the information I needed in my quest I had to
import android.content.ContentValues;
import android.content.Intent;
import android.content.Context;
import android.os.Environment;
import android.view.ViewConfiguration;
within my .dll. If there is no scope it cant be found. I think you already know this and probably more than me on the subject, so apologies. Perhaps you can wrap it in a nice class or namespace or something.
Answer by liortal · Aug 14, 2014 at 12:59 PM
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.
I have same issue, and I try this answer than got error "ClassNotFoundException".
$$anonymous$$y Java Class Interface is under the main class, like :
package com.unity.test;
public class UnityTest {
public IListenerCallBack _callback = null;
public void SetCallBack(IListenerCallBack cb) {
_callback = cb;
}
public void DoCallBackSucess() {
_callback.onSuccess("Success", "please");
}
public void DoCallBackError() {
_callback.onError("DoCallBackError");
}
public interface IListenerCallBack {
void onSuccess(String var1, String var2);
void onError(String var1);
}
}
And my C# Class
public class TestJarCallBack : AndroidJavaProxy
{
public TestJarCallBack():base("com.unity.test.UnityTest.IListenerCallBack")
{
}
//... void onSuccess
//... void onError
}
Is any idea? Plz!!!
Answer by vladimirg · Nov 13, 2013 at 04:50 PM
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.
Follow this Question
Related Questions
Can I use platform-specific UIs 1 Answer
Android Plugin in Unity - No Return Value 0 Answers
CreateJavaRuntime problem 0 Answers
Android Plugin in Unity - No Return Value 0 Answers
Just how slow is the JNI? 0 Answers