Version: Unity 6.7 Alpha (6000.7)
Language : English
Best practices for calling Java/Kotlin code
Integrating Unity into Android applications

Calling C# code from Java and Kotlin plug-in code

Java and Kotlin plug-in code can call your C# scripts, for example, to notify Unity of an Android event or to return a result from your plug-in code. There are two ways to do this:

  • Send a message to a GameObject with UnitySendMessage.
  • Call a C# method through a callback interface with AndroidJavaProxy.

For the equivalent C# to Java and Kotlin implementation, refer to Calling Java and Kotlin plug-in code from C# scripts.

Note: To debug either approach, set AndroidJNIHelper.debug to true to log the JNI activity that Unity performs for each call.

Send a message to a GameObject

Use UnitySendMessage to send a string from Java or Kotlin plug-in code to a method on a named GameObject. This is a one-way call where the C# method receives the string but doesn’t return a value to the plug-in. Use it for simple notifications.

The plug-in calls UnitySendMessage with three arguments: the name of the target GameObject, the name of the method to call, and the string message.

The following Java example implements UnitySendMessage:

package com.example.androidplugin;

import com.unity3d.player.UnityPlayer;

public class MessageSender {
    public static void sendToUnity(String gameObjectName) {
        UnityPlayer.UnitySendMessage(gameObjectName, "OnMessageReceived", "Hello from Java");
    }
}

The following Kotlin example implements UnitySendMessage:

package com.example.androidplugin

import com.unity3d.player.UnityPlayer

object MessageSender {
    @JvmStatic
    fun sendToUnity(gameObjectName: String) {
        UnityPlayer.UnitySendMessage(gameObjectName, "OnMessageReceived", "Hello from Kotlin")
    }
}

In your C# script, add the method that UnitySendMessage calls. Ensure the script is attached to a GameObject whose name matches the first argument.

using UnityEngine;

public class MessageReceiver : MonoBehaviour
{
    void Start()
    {
        gameObject.name = "MessageReceiver";
        using var sender = new AndroidJavaClass("com.example.androidplugin.MessageSender");
        sender.CallStatic("sendToUnity", gameObject.name);
    }

    void OnMessageReceived(string message)
    {
        Debug.Log("Message from plug-in: " + message);
    }
}

This example:

  1. Sets the GameObject’s name to match the target name the plug-in sends.
  2. Calls the plug-in, which uses UnitySendMessage to send a string back to the OnMessageReceived method on the named GameObject.
  3. Logs the message that the plug-in sends.

Note: In this example, C# calls the plug-in directly to trigger the message, so you can run the example without an Android event. In a real project, the plug-in calls UnitySendMessage in response to an Android event, such as a button tap or a lifecycle callback.

UnitySendMessage has the following limitations:

  • You can only call C# methods with the signature void MethodName(string message).
  • Calls are asynchronous and have a delay of one frame.
  • Multiple GameObjects with the same name can cause conflicts.

To send data other than a string, serialize it to a JSON string. For more information, refer to Supported data types for Java/Kotlin and C# code.

Call a C# method through a callback interface

Use AndroidJavaProxy to implement a Java or Kotlin interface in C#. When the plug-in calls a method on the interface, Unity runs your C# implementation. Use this approach for typed callbacks, or to pass structured data or return values.

Define an interface in the plug-in and a class that calls it. The following plug-in code calls the interface method to pass a message back to C#.

Java plug-in code

package com.example.androidplugin;

public class Greeter {
    public interface GreetingCallback {
        void onGreeting(String message);
    }

    public void requestGreeting(GreetingCallback callback) {
        callback.onGreeting("Hello from Java");
    }
}

 Kotlin plug-in code

package com.example.androidplugin

class Greeter {
    interface GreetingCallback {
        fun onGreeting(message: String)
    }

    fun requestGreeting(callback: GreetingCallback) {
        callback.onGreeting("Hello from Kotlin")
    }
}

In your C# script, create a class that derives from AndroidJavaProxy and implements the interface. Pass an instance of this class to the plug-in.

using UnityEngine;

public class GreetingExample : MonoBehaviour
{
    class GreetingCallback : AndroidJavaProxy
    {
        public GreetingCallback() : base("com.example.androidplugin.Greeter$GreetingCallback") { }

        void onGreeting(string message)
        {
            Debug.Log("Greeting from plug-in: " + message);
        }
    }

    void Start()
    {
        using var greeter = new AndroidJavaObject("com.example.androidplugin.Greeter");
        greeter.Call("requestGreeting", new GreetingCallback());
    }
}

This example:

  1. Creates a C# GreetingCallback class that derives from AndroidJavaProxy and passes the interface name to the base constructor. Because GreetingCallback is nested in the Greeter class, the name uses the $ separator: com.example.androidplugin.Greeter$GreetingCallback.
  2. Implements onGreeting with a signature that matches the interface method. Unity automatically routes calls on the interface to this C# implementation.
  3. Creates an AndroidJavaObject for the Greeter plug-in class and calls requestGreeting, passing the proxy. The plug-in then calls onGreeting, which runs the C# implementation.

Note: In this example, the plug-in calls the interface method on Unity’s main thread. If your plug-in calls the method from a background thread, the C# implementation also runs on the background thread. In this case, use AndroidApplication.InvokeOnUnityMainThread to run any Unity API calls on the main thread.

For more information on writing the plug-in code, refer to Java and Kotlin source plug-ins.

Additional resources

Best practices for calling Java/Kotlin code
Integrating Unity into Android applications