Unity Android plugin tutorial (1/3) Fundamentals

While Unity Android plugin development enables deep integration with mobiles, finding the right Unity Android plugin workflow is not that easy as you might think. Many sources encourage extending UnityPlayerActivity, as the source of your plugin, however, this approach really sources compatibility issues with other plugins. When you making Unity Android plugins for a single Unity project, constant surgery for inheritance and manifests can resolve these issues with multiple plugins.

But if you want your plugin towork seamlessly with other plugins, once you are planning to release a plugin to the public, or want to encapsulate it for further projects, I strongly advise against “subclassing UnityPlayerActivity / Android manifest tweaking” approach. Instead, create a modular, encapsulated plugin on its own, like most of the plugins created.

Just by simply Google for UnityPlayerActivity you’ll easily find issues complaining about broken projects, incompatibility issues with Vuforia, Facebook, and more.

TL;DR

While I think plugin development needs deeper / complete insight into the backgrounds as well, I know some people find working code the best source of understanding, so you can simply checkout the corresponding Unity Plugin project from GitHub, install Android Studio, and inspect the internals, or start develop your plugin straight into.

eppz! Alert - Unity native plugin (iOS / Android) example / boilerplate project.

eppz! Alert – Unity native plugin (iOS / Android) example / boilerplate project.

Checkout eppz! Alert at

Unity Android runtime

The Unity Android runtime is implemented in UnityPlayer, a special View class subclassing FrameLayout (a view designed to typically hold a single subview). Upon creation, this view instantiates a special view type SurfaceView that is suitable for direct drawing with OpenGL as the single subview. This is quiet similar to the iOS architecture, where Unity tweaks the underlying layer of a UIView to draw it directly by OpenGL. Beside drawing to this surface, this class implements behaviours regarding native features like touches, keyboard, location, camera, networking, application states among some others. While this UnityPlayer implements the most of the native features, it is not the entry point for the application.

In this actual hierarchy capture, at the end of the view hierarchy you can see a UnityPlayer (a FrameLayout subclass) that contains a SurfaceView to carry out Unity OpenGL drawing.

In this actual hierarchy capture, at the end of the view hierarchy you can see a UnityPlayer (a FrameLayout subclass) that contains a SurfaceView to carry out Unity OpenGL drawing (unfortunately rendered content cannot be previewed in Android Monitor).

Android apps, and the OS in general are made of a huge pile of many Activity, which is basically a single screen the user interacts with (more on this at Android Application Fundamentals). Activities can be started by other Activities, or by the user. If an Activity contained in an application is marked as the main Activity, the OS will start it up once the user tapped the icon of the app (more on Launcher Activity).

In a generic Android Unity application, the main (launcher) Activity is UnityPlayerActivity. If you take a look at a compiled AndroidManifest.xml file in the APK, you can see how it marks UnityPlayerActivity to be the MAIN and LAUNCHER Activity of the application. Parts of the compiled APK can be found at Temp/StagingArea of a Unity project (after you build to Android). I also decompiled the Unity Player for Android, so you can see all these details by yourself in the repo below.

Inspect decompiled Unity Player for Android (UnityPlayer.jar) at
...
<activity android:label="@string/app_name"
          android:name="com.unity3d.player.UnityPlayerActivity"
          ...
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
    </intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
...
The Android runtime of a Unity application is carried out in a UnityPlayerActivity instance.

The Android runtime of a Unity application is carried out in a UnityPlayerActivity instance, that embodies a single OpenGL screen the user can interact with. In the application manifest, this Activity is marked as the main / launcher activity.

UnityPlayerActivity is really a homely ~70 line class, instantiating the UnityPlayer instance and set it as the content view for this Activity, for the entire application. Beside this, it stands there to dispatch native events to UnityPlayer.

public class UnityPlayerActivity extends Activity
{
    protected UnityPlayer mUnityPlayer;
    protected void onCreate(Bundle bundle)
    {
        this.requestWindowFeature(1);
        super.onCreate(bundle);
        this.getWindow().setFormat(2);
        this.mUnityPlayer = new UnityPlayer(this);
        this.setContentView(this.mUnityPlayer);
        this.mUnityPlayer.requestFocus();
    }

    ....

    public boolean onTouchEvent(MotionEvent event)
    { return this.mUnityPlayer.injectEvent(event); }

    ...
}

Poor man’s Unity Android plugin architecture

Native features are mostly considered as external services from the viewpoint of a Unity application, so the intuition for that is to create a singleton being the single access point for the features (like Google Analytics, Facebook, Chartboost services are also singletons mostly). When looking up Android Plugin best practices, at the time of this writing the common suggestion is to subclass UnityPlayerActivity augmented with plugin features, then tell the application to substitute the Launcher Activity with this new class.

It is a common Unity Android plugin development suggestion to subclass UnityPlayerActivity, and make the new class the Launcher Activity of the entire application.

It is a common Unity Android plugin development suggestion to subclass UnityPlayerActivity, and make the new class the Launcher Activity of the entire application.

In this Unity Android plugin tutorial series, we use eppz! Alert project as the example, a simple plugin that pops up usual native alert views, and calls back when user selected an option. On iOS it uses UIAlertController, on Android it uses DialogFragment / AlertDialog for this, then calls back to Unity with the results using UnitySendMessage.

While this feature feels a tiny little component of an application, it is still suggested that we should create an entirely new Launcher Activity for our Android application. If I wanted to use my plugin in concert with other plugin(s) – like I had to with Vuforia -, the resulting class hierarchy would have looked like below.

Using UnityPlayerActivity subclassing method, working with multiple Unity Android plugins results a linear, unwillingly cross-dependent class hierarchy.

Using UnityPlayerActivity subclassing method, working with multiple Unity Android plugins results a linear, unwillingly cross-dependent class hierarchy.

Where to implement Unity Android plugin?

As I outlined above, a plugin really should contained in a single class that implement some features, composited into the main application, typically through a static public interface. A plugin I made for a recent project (mainly photography and emailing with attachments) was meant to be released to the Unity Asset Store from the very beginning, so me personally never subclassed the main application Activity. I really wanted to avoid compatibility issues and ship an encapsulated, self-contained little piece of software.

Knowing that Android Activity is basically a screen provided to the user to interact with it, having the entire Unity experience wrapped into an Activity sounds fair. From the OS point of view, it is a single OpenGL screen where the user interacts with the app.

My first encapsulation attempt was to create a separate Activity for my plugin, so I can compose it to the main Activity. An Activity is also perfect for interacting with native Android features, as it can easily start further Activities (like photography, sharing, etc.), also has built in hooks to recieve callbacks / signals from other Activities (see onTouchEvent example above). I’m still really a beginner Android developer, but I learned that not being in an Activity context makes things difficult.

So wrapped / encapsulated the plugin into an Activity class, and started (activated) it. That forced the running UnityPlayerActivity became inactive, left me with a black screen while the plugin Activity instance was retained and running. I made attempts to simply wrap the plugin into a generic class, but reaching out for native Android features (and get callbacks) suddenly became really cumbersome. The bottleneck was to get callbacks from Activities when using startActivityForResult().

Some may use global BroadcastReceiver, or narrow down to local broadcasts using LocalBroadcastManager, but still really feels an overhead, and still no luck with startActivityForResult(). This tutorial – Creating a native Android plugin for Unity3d – however by Ashley Davis and Rory Dungan really does a great job on creating a nicely packed Unity Android plugin using this technique. I also inspired a lot from that work.

Next attempt was to wrap plugin into a Service, which seemed really promising from the really beginning. They are something like Activities (can be declared in AndroidManifest.xml in a similar manner), but without a UI, ability to run in background. Launching other Activities and get callbacks still remained an issue, so I felt it risky for use. The direction however was fine, as at this point I started to experiment to create Activities without UI.

Composited Unity Android plugin architecture

At this point I found Fragments, according to the official documentation “A Fragment represents a behavior or a portion of user interface in an Activity.”. Sounds exactly I was looking for.

Basically a class something like a smaller sub-activity, that can be started even without a UI. Absolutely perfect to carry out additional sub-services of a given Activity, even as it suggested by the documentation: “You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running (sort of like a “sub activity” that you can reuse in different Activities)”.

That sounds as like a plugin on its own. Also it is nicely embedded in the UI / Activity hierarchy, so every native / UI feature is fairly accessible from there. Many Activities we will start from our plugins will probably call back with their respective results, and fortunately Fragments implement onActivityResult() callbacks, like Activities do. This momentum was key, when I was working with email Activities for example. And on the top of it, while it is working fine with Activities, still does not need any entry in AndroidManifest.xml!

Its a perfect fit for being a “modular section” of UnityPlayerActivity, so since than I’m keep using Fragment based Unity Android plugins.

Encapsulating Unity Android plugins in Fragments results in a much more modular architecture. Application domain and plugin domain is completely independent, nor plugins interfere with each other.

Encapsulating Unity Android plugins in Fragments results in a much more modular architecture. Application domain and plugin domain is completely independent, nor plugins interfere with each other.

Compositing Unity Android plugin Fragments to the main Activity

Compositing a Fragment instance to the main UnityPlayerActivity can be simply by instantiate in a factory method, then add the Fragment to the Unity Activity (UnityPlayer holds a static reference to that in currentActivity).

package com.eppz.plugins;

public class EPPZ_Alert extends Fragment
{


    public static EPPZ_Alert instance; // Singleton instance


    public static void start()
    {
        // Instantiate Fragment.
        instance = new EPPZ_Alert_Fragment();

        // Add to the current 'Activity' (a static reference is stored in 'UnityPlayer').
        UnityPlayer.currentActivity.getFragmentManager().beginTransaction().add(instance, "EPPZ_Alert").commit();
    }

    ...

}
See full EPPZ_Alert.java at

Starting it up from Unity is like the snippet below. Simply locate the plugin class, then call the static initializer method start() created above.

public class EPPZ_Alert_Android : MonoBehaviour
{

	AndroidJavaClass _class;
	AndroidJavaObject instance { get { return _class.GetStatic("instance"); } }

	void Start()
	{
		// Start plugin Fragment.
		_class = new AndroidJavaClass("com.eppz.plugins.EPPZ_Alert");
		_class.CallStatic("start");
	}

	...

}
See full EPPZ_Alert_Android.cs at

Having this the rest of the plugin can be implemented in the Fragment subclass. At our application’s runtime, Unity will have a single retained instance of our plugin (like a background service), so we can simply call implemented plugin methods directly on the Fragment instance.

Unity native plugin workflow

If you are already familiar with Unity plugin creation, you should just start maintaining you Android plugins in Fragment classes to leave the world better than you found it.

The rest of the tutorial series are mainly about creating a healthy Unity plugin workflow, covering issues like the iOS counterpart, Android Studio / Xcode native plugin project setup, compile post-processing, common Unity C# interface (that communicates with the Unity application and hides multiplatform code), compact project folder structure, and more.

Thanks for reading! Well, if you are still reading this, you are probably a curious mind, so may proceed to Unity Android Plugin Tutorial 2. Project setup (in progress), a tutorial with more emphasis on practical details, with lot more code, lot less talking.

  • Benjamin Wonder

    Thank you so much!!!!!!!

  • Benjamin Wonder

    Do you know how to get this plugin working:
    http://pastebin.com/8TxC51ty
    Due to the fact that “protected void onNewIntent(Intent intent)” is not on fragments ?

    • This article is about how to create / publish your own plugins, not on how to deal with others in Unity. I’m not intended to support third party code. You should probably chain up your multiple plugins to a single Activity, but you’d better ask the providers you’re dealing with.

      When thinking plugin, I personally would try to avoid using Activities. Supposing you’re attempting to use Nfc Android Java Plugin For Unity 3d codebase, I think you may listen to NFC using BroadcastReceiver, something like this.

      • Benjamin Wonder

        Thank You!
        I tried (successfully) listening to NFC unsing a BroadcastReceiver on a Fragment Class but this is just possible using the ACTION_ADAPTER_STATE_CHANGED filter action which is just called when NFC is enabled or disabled.
        So I can’t get the needed NdefMessage.
        Therefore a Forground Dispatcher is needed which I think is just possible to use with an Activity.

        I tried to start an Activity (MyClass) in Java with:

        Intent myIntent = new Intent(UnityPlayer.currentActivity, com.foo.myplugin.MyClass.class);
        UnityPlayer.currentActivity.startActivity(myIntent);

        And in AndroidManifest.xml

        but without luck. (Logcat: Unable to find explict activity class – for whatever reason)

        Do you have any other idea get this working ?
        Is there a way to instanciate my own activity, do the NFC stuff and then switch back to the Unity activty and go on?

        • Please use stackoverflow if you need help on starting Activities, and NFC stuff.

          As this issue feels me rather specific, I suggest you to export / import Google Android Project from Unity, and create / debug your plugin in Android Studio first. You can iterate way faster that way.

          Please use <pre> and <code> tags in your comments for the greater good.

  • Fabio Blanca

    This is the best piece of information regarding Android native plugins for Unity on the Web. Thanks for sharing this. I’m looking forward the next chapters

    • Thanks for the words. When I had to create my own plugins, I also felt lost amongst the materials across the webs.

      Nor Unity itself does not help too much on the respective Building Plugins for Android article. What it does to encourage subclassing UnityPlayerActivity, source of such many intercompatibility headaches among plugins all over.

      Best would be if Unity was provide a separate base class for Android plugins, with all the methods hooked up that the main activity can respond to. Then UnityPlayer could resolve every implemented class at startup, and enqueue them for dispatching Activity hooks during runtime (or in background as well).

      This would be perfect for such cases @Benjamin have.

      • Fabio Blanca

        Exactly like you said, I was having a hard time trying to integrate a simple plugin I developed myself into a project that has other 3rd party plugins. My issue was that I was extending UnityPlayerActivity as mentioned on Unity Official docs and other posts on web.
        After reading this I was able to refactor my plugin and it’s now currently working as I needed in my project alongside those other 3rd party plugins.
        Thanks again! 🙂

  • Sanket Prabhu

    Hi.. You are really techno geek. I follow all 3 tut but i am not believing how is going to happen. you are magician . I want to know how unity import .aar from outside the asset into plugin folder. please explain

    • This is carried out using Gradle. Take a closer look at Post-process plugin archive in Unity Android plugin tutorial (2/3) Project setup and workflow.

      This part does copy / rename actually:

      task(deployTaskName, dependsOn: dependencyTaskName, type: Copy) {
      from(sourceAARFolder)
      into(targetAARFolder)
      include(sourceAARName)
      rename(sourceAARName, targetAARName)
      }.group = deployTaskGroup;

      • Sanket Prabhu

        ohhh got it….Actually Im AR developer (Vuforia+Unity). Thanks bro, your content is really useful

  • Doo Hyun Park

    This is absolutely greatest article for android plugin. I’m working with GVR in my Unity Project but it is so difficult to make android plugins because GVR already has AndroidManifest.xml . I think this series of article give me a light. Thank you so much!!

  • Nuno Monteiro

    This is pure gold!
    Thank you so much for taking the time to compile this beautiful tutorial!

    You rock!

    • Glad you’re using it 🙂