This post is a quick guide on getting started with developing a plugin in Unity which will allow you to interface and call commands from an Android project, therefore giving you access to native functionality that might not be available in Unity’s standard library.
Creating a plugin in Android Studio
Create a new empty project - plugin will be stored as individual modules within this project. Create a new module by going to to File > New > New Module… > Android Library. Then, create a new empty class:
We’ll add some test methods and see how to call them from Unity soon.
For Unity to recognize your plugin, you’ll need to compile it to a [YourProjectName][YourModuleName]\build\outputs\aar. Move this file inside the Assets\Plugins\Android folder of your Unity Project. We can now access this plugin from Unity.file. Click on the “Gradle” tab on the right-most side of the window, click on your module > Tasks > build > assembleRelease. This will generate a file in
You’ll need to repeat the building procedure every time you make a change to the plugin in Android Studio.
Creating plugin objects
In Unity, you can create a representation of your Android plugin by creating a new/ object and passing your package name and class name:
Let’s say you have those two methods in your class to print test messages:
You can call methods from your plugin class with
Bear in mind you can’t call non-static methods from aobject.
Difference between AndroidJavaClass and AndroidJavaObject
only calls an instance of an activity (it does not create it). creates a new object class (basically like calling ). Therefore if you need to call static methods only it is recommended to use . If, however, you need to call a non-static method or have the necessity to create the class (to set its context, or use functionality like for example) you’ll have to use . Note that when a is initialized, its constructor will be called (and not !). You can still call static methods from
Calling methods with context
Some Android operations need to operate within a context.
A context object is the context of current state of the application/object. It lets newly-created objects understand what has been going on. Typically you call it to get information regarding another part of your program (activity and package/application).
For example, if we were to start a new service or activity, we’d have to do so from a context (usually the activity you’re calling the method from). In Unity programs, we’ll pass the activity generated by UnityPlayer. You can access it like this:
Then you can pass the activity as a context to the necessary methods. Let’s say you’ve got a method on your plugin class which sets the context later used by other methods:
From Unity, you’d call:
To successfully start the service. If you were to call themethod without setting its context first, you’d get a when the method tries to access the necessary context.
Calling methods on the UI thread
Typically when you write a traditional Android app there is only one main thread, and everything that deals with the UI must run on the main thread. Unity runs its own thread to handle its processing. It doesn’t usurp the Android main thread created by the Android OS when launching the app. If you want to do anything in the Android UI outside of Unity, for example showing a toast or a dialog, you’ll have to run it in the main thread.
For example, take a method in your Android plugin which shows a Toast:
You can run this method on the main thread by callingfrom the main Unity activity and pass the method you want to call as a Runnable.
If we need more advanced form of communication between our plugin and Unity, for example invoking callbacks from Unity objects, we need to make our plugin class an extension of UnityPlayerActivity.
First we need to find the Unity Java classes sources. They are located into a classes.jar file found in the installation folder (usually C:\Program Files\Unity\Editor\Data (on Windows) or /Applications/Unity (on Mac)) in a sub-folder called PlaybackEngines/AndroidPlayer/Variations/mono or il2cpp/Development or Release/Classes/.
Then, we need to tell Android Studio to compile the classes.jar file alongside our plugin. You can do so by moving the classes.jar file to the \libs folder of our plugin project folder. By not doing so, the UnityPlayerActivity won’t be found / recognized when extending our class.
The classes.jar file, however, is included into the Unity Android build by default, and Unity will fail to build the application when finding duplicate classes.
We can fix this with a little hack: create and empty module in your project (call it something like “unitylibrary”), and then put the classes.jar file into its /libs folder. Then, in thefile of the original plugin module, add the dependency to the empty unitylibrary module like so:
This way, the UnityPlayerActivity class definition will be recognized in your code, but the classes.jar won’t be packed inside your plugin.
Bear in mind that even if your main class in the plugin extends an Activity, it doesn’t actually gets created -is not called, and any method which would normally work within the context of the activity has to be called from the context of the Unity application’s UnityPlayerActivity which we pass from our scripts: not instead of , instead of and so on…
Unity Callbacks from the Plugin
Once the class extends UnityPlayerActivity, we can call the static method, where - is the name of the GameObject in your Unity scene to communicate with - is the function to call on that GameObject - is the data (String) to pass to this function
Therefore, let’s make a test function in our Android class like:
And then, in aGameObject in Unity, write those methods:
When you call thefunction, the Android plugin will call the function, invoking the function in . If everything worked fine, you’ll see the “A little bird told me: Hello from Android” message in the Log.
From my experience, I noticed that if you create aof a class that extends , you’ll have to run the declaration on the UI thread: