HowTo: native Android plugins for Unity3D

Unity logo

This article is part 2 of the series on Creating native mobile plugins, you can find part 1 here.
In the previous part we talked about the way to create, code and implement a Unity3D native plugin for iOS.
This time we will be covering the Android platform and creating a native Unity3D plugin for that platform.

This article will cover the creation an .AAR file.

The AAR file type is primarily associated with ‘Axis Archive’ by Apache Software Foundation. Compressed file package for Apache Axis 2 which contains classes and data for a Web Service. The AAR is a JAR (Java Archive) file and is therefore based on the standard ZIP file format.

Now that we have that covered, let’s start creating our native plugin.

1. Toolset

  • A computer
  • Android Studio Editor software
  • An Android device to test/compile on
  • Android coding knowledge, as I am not covering the language itself.

2. Android project setup

A. Open Android Studio and create a new Android Project.
Give your project a name and a namespace.

project_creation_01

Select the supported platforms for your application.

project_creation_02

Finally “Finish” the project setup.
Your project has now been created.

B. Create a new Android Module, of type “Android Library”
Go to “File” -> “New” -> “New Module…”
This will bring up the module creation window.

Select “Android Library”.

Android_module_01

Give your library a name, and a namespace…

Android_module_02

Now finish your library creation.

3. The Android part

Now that your project has been setup, let’s look at the android/java code of our native plugin. In contrast of Objective-C, a Java class only has 1 file. So no header and body files.

We want our native plugin to print a string passed from Unity3D.

First thinks first,
Select your module src folder: projectFolder -> moduleFolder – > src – >main -> java -> yourPlugin_folder
right click and select “New” -> Java Class.

For our example we will use our class “Bridge“.

package plugins.twnkls.com.mylibrary;

//import needed packages / classes.
import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.widget.Toast;
import android.util.Log;
import android.os.Looper; //extend android application.

public class Bridge extends Application
{
  // our native method, which will be called from Unity3D
  public void PrintString( final Context ctx, final String message )
  {
    //create / show an android toast, with message and short duration.
    new Handler(Looper.getMainLooper()).post(new Runnable() {
      @Override
      public void run() {
        Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show();
      }
    });
  }
}

The above piece of code takes 2 parameters,

  1. the current android context
  2. the message that will be shown.

It’s very simple and pretty straight forward.
That’s it for our plugin code.

5. Compiling your Native Library

Now that we have our plugin code and module setup, let’s have a look at getting our native plugin compiled.
For this you have to make sure that the minimum support SDK is the same as you have specified inside Unity3D.
By default unity sets it’s minimum SDK version to 9.

unity_android_version

* You can find this setting in the Android Build Settings panel inside Unity3D

Thus you have to make sure that your Android project has that same version as it’s minimum SDK version.
To change the minimum SDK version for our Android Module, go to “File” – > “Project Structure”
Once there, select your Android Module and select the tab “Flavors”. You can change the minimum SDK version here.

AndroidStudio_android_version

To compile our Android Module press the “Make Project” button ( CTRL + F9 ) in your toolbar.

btn_make_project

Once the action is done, you are ready to use your native Android plugin. Open your module folder in your OS explorer and go to the “outputs / aar ” folder. Here you will find the release and debug versions of your native plugin. For this example we will use the release version.

6. Implementing the native plugin inside Unity3D.

Open your Unity3D project and make sure you have the following folder structure:
Assets / Plugins / Android

Place your native android .AAR file inside this folder.

Now let’s write some code to call the plugin.

//basic imports.
using UnityEngine;
using System.Collections; //standard unity behaviour.

public class AndroidCaller : MonoBehaviour
{
  //method that calls our native plugin.
  public void CallNativePlugin() {
    // Retrieve the UnityPlayer class.
    AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");

    // Retrieve the UnityPlayerActivity object ( a.k.a. the current context )
    AndroidJavaObject unityActivity = unityPlayerClass.GetStatic("currentActivity");

    // Retrieve the "Bridge" from our native plugin.
    // ! Notice we define the complete package name.              
    AndroidJavaObject bridge = new AndroidJavaObject("plugins.twnkls.com.mylibrary.Bridge");

    // Setup the parameters we want to send to our native plugin.              
    object[] parameters = new object[2];
    parameters[0] = unityActivity;
    parameters[1] = "This is an call to native android!";

    // Call PrintString in bridge, with our parameters.
    bridge.Call("PrintString", parameters);
  }
}

Add “CallNativePlugin” to a button click inside Unity3D, and you’re ready to test your native plugin!

To test your project, attach an Android device to your computer and run your project on your device. After clicking the button you should see an native Android Toast showing your passed text.
Here’s a screenshot of what your app should look like.

Screenshot_2016-06-16-11-41-56

You are now an Android plugin master! 🙂
Happy coding!

HowTo: native iOS plugins for Unity3D

Apple logo and Unity logo

Here at TWNKLS, we are used to develop in many different programming languages and platforms. One of the platforms we use a lot is Unity3D.

When developing a new mobile application, we would often see a need for custom mobile logic that Unity3D does not support out of the box.
Actions like taking a picture and saving it to the camera roll or even sending an in app email would fit the “custom mobile logic” description and would thus be build as a native plugin. So how is a native plugin built you may ask? Well, that’s exactly what this article is about!
In this article I am going to take you through the steps of building a native mobile compiled plugin for use in Unity3D.

When talking about mobile development, we generally mean 1 of 2 platforms.
Namely iOS or Android.
Let’s start with iOS.

1. Toolset

  • An Apple computer.
  • XCode IDE.
  • An Apple device to compile on (also Apple simulators).
  • Objective-C coding knowledge, as I am not covering the language itself.

2. XCode project setup

A. Open XCode and create a new iOS static library project.

iOS_create_xcode_project

B. Give your plugin a name and namespace.
Namespaces generally follow these rules : Domain – Company – PluginName

iOS_namespace

C. Finish the project creation process.
Your project structure should look like the following:

iOS_project_view

The files in red indicate that those files are not yet valid.
For now, don’t worry about them. We will cover them in a later stage.

3. The Objective-C part.

Now that your project has been setup correctly, let’s dive into some objective-C code. A typical Objective-C class has 2 components, a header (.h ) and a body (.m) file. We will start with our header file.
The header file is typically viewed as an “interface”, defining parameters and methods.

//import the basics.
#import "Foundation/Foundation."

//start interface.
@interface MyNativePlugin : NSObject  //extend from basic object.

//define variables.
@property ( retain, nonatomic ) NSString* dummyString;

//define methods.
-(id) init;
-(void) doMyNativePluginStuff: (NSString*) passed_name;

//end interface. 
@end

In the piece of code described above, we define an interface called “MyNativePlugin.h” which has two methods, namely “init” and “doMyNativePluginStuff”.
The first accepting no parameters and the latter accepting one string parameter. The interface also defines a class variable called “dummyString” of type NSString.

Next up is the corresponding body file.
A body typically incorporates the variables and methods defined in the header.

//import the header file.
#import "MyNativePlugin.h"

//start implementation.
@implementation MyNativePlugin

//synthesize variables.
@synthesize dummyString;

//define methods.
-(id) init {
   return self;
}

-(void) doMyNativePluginStuff: (NSString*) passed_name {
  //Do something with the passed name.
  //Here we just log the passed_name
  NSLog( @"%@", passed_name );
}

//end implementation.
@end

That’s it for our plugin code.

Next step is to setup a connection point for Unity3D with which it can communicate with our code. This is typically done through the UnityAppController. When Unity3D creates a XCode project, it creates a main entry point for the Objective-C application. This entry point is the UnityAppController.

There are multiple ways to make the connection with our plugin:

  • Subclass the AppController
  • Inject code at compile time through Post Process Build scripts.
  • Open the UnityAppController and hand-code your custom code inside.

Our goal is to get our class initialized on start-up AND call our class after some unity event.
We could open the UnityAppController files and code our initialization and implementation code inside of these files. But the downside is that every time Unity3D builds ( or replaces ) a new xCode project, you will have to do this manual coding stuff again…. and again…. and again.

We definitely need something more robust and automated.
What we need is to subclass the UnityAppController to keep all unity generated codes but easily implement our own.

Enter “IMPL_APP_CONTROLLER_SUBCLASS
IMPL_APP_CONTROLLER_SUBCLASS is a method that will take a class as parameter, subclasses it from UnityAppController and make it the new AppControlller being called by Unity3D as entry point.
For this to work we need to make our own UnityAppController implementation with our codes.
This can be fairly simple.
Below a quick 1 file implementation of an AppControlller subclass (header and body in 1 file )

#import "MyNativePlugin.h" //our newly made plugin.
#import "UnityAppController.h" //our link to the base class.

//------- start header ----------------
//start interface.
@interface MyNativePluginAppController : UnityAppController  //extend from UnityAppController.

@property ( retain, nonatomic ) MyNativePlugin* myNativePlugin;

//define methods.
-(void) initNativePlugin;
-(void) doCallNativePlugin:(NSString*) name;

//end interface.
@end

//------- start body ---------------
@implementation MyNativePluginAppController

//synthesize variables.
@synthesize myNativePlugin;

// overriding main unity entry point.

-(void) startUnity: (UIApplication*) application {
   [super startUnity: application];  //call the super.
   [self initNativePlugin];          //call method to initialize our plugin class.
}
-(void) initNativePlugin {
   myNativePlugin = [[myNativePlugin alloc] init];  //initialize our plugin class.
}

-(void) doCallNativePlugin:(NSString*) name {
  [myNativePlugin doMyNativePluginStuff:name ];  //call plugin
}

@end

//setting this as app controller.
IMPL_APP_CONTROLLER_SUBCLASS( MyNativePluginAppController )

Save this file as MyNativePluginAppController.mm

A small recap of what we just did.

  1. We created a class to hold our custom plugin code called MyNativePlugin.
  2. We created a main entry point which subclasses UnityAppController and initialises our plugin class on start-up called MyNativePluginAppController.

Let’s continue our journey.

4. Building the connection with Unity3D.

In order for Unity3D to call our Objective-C, we will need something that is called an “ extern C ” method. This method defines a method which will be exposed externally and can be called from Unity3D. Because our flow goes from Unity3D to Objective-C, this method will need to be in our Objective-C entry point, thus the MyNativePluginAppController.mm needs to be modified to have such a method.

//import the basics.
#import "MyNativePlugin.h" //our newly made plugin.
#import "UnityAppController.h" //our link to the base class.

//------- start header ----------------
//start interface.
@interface MyNativePluginAppController : UnityAppController //extend from UnityAppController.

@property ( retain, nonatomic ) MyNativePlugin* myNativePlugin;

//define methods.
-(void) initNativePlugin;
-(void) doCallNativePlugin:(NSString) name;
//end interface.
@end

//------- start body ---------------
static MyNativePluginAppController delegateObject; // --- a static object is defined to be called from "extern" method.

@implementation MyNativePluginAppController

//synthesize variables.
@synthesize myNativePlugin;

// overriding main unity entry point.

-(void) startUnity: (UIApplication) application { 
   [super startUnity: application]; //call the super.
   [self initNativePlugin]; //call method to initialize our plugin class.

   delegateObject = self; // --- we assign this instance to the static delegateObject.
}

-(void) initNativePlugin {
   myNativePlugin = [[myNativePlugin alloc] init]; //initialize our plugin class.
}

-(void) doCallNativePlugin:(NSString) name {
   [myNativePlugin doMyNativePluginStuff:name ]; //call plugin
}

extern "C" { // -- we define our external method to be in C.
   void CallNativePlugin( const char* name ){
   NSString* justName = [[NSString alloc] initWithUTF8String:name]; // -- convert from C style to Objective C style.

   [delegateObject doCallNativePlugin:justName ]; // -- call method to plugin class
 }
}

@end

//setting this as app controller.
IMPL_APP_CONTROLLER_SUBCLASS( MyNativePluginAppController )

This will conclude the MyNativePluginAppController.mm

A small recap.

  1. We created our plugin class which will do our native stuff.
  2. We created our UnityAppController subclass, which has our custom initialization methods.
  3. We added a “delegateObject”, which is a static variable in the UnityAppController class of type MyNativePluginAppController.
    We need this to be static because the “extern” method cannot access variables defined inside the AppController subclass. This way, we ensure it is always accessible.
  4. We assigned the instance of the UnityAppController subclass to the delegateObject in startUnity.
  5. We added an “Extern” method which Unity3D can call and will trigger our plugin.

!! It is important to have our newly made UnityAppController subclass saved outside of our xCode project.
At compile time, Unity3D creates a new ( or overwrites the old ) project. By saving the file inside your xCode project Unity3D will remove / overwrite it.
We will add this later inside the Unity Project.

5. Compiling our native library.

Now that we have our project setup and coded correctly we are about to compile the project into a native static library ( .a file ).
For this to work correctly we have to connect our iOS device ( preferably a 64 bit ) to our computer.
Select the project in the project view and make sure you have the correct architectures selected.

iOS_architectures

For this plugin I am going to support the following device architectures:

  1. ARMv7
  2. ARM64

Other device architectures that can be supported are

  1. ARMv6
  2. ARMv7S

These are the architectures on which your plugin will run. Other architectures will fail loading the plugin as you have not supported them.

Now select the correct target and set the target device to the connected device.

iOS_targets

With these steps setup correctly, press “RUN” or the Play button.

If all goes well, your static library has now been made.
You will get errors if this fails, but if not you’ll see your “red files” in project view become black.

iOS_compiled

Right click the .a file and select “Show in finder”, which will take you to the file location.

Congratulations!
You have successfully compiled an iOS library which can be used in Unity3D projects for iOS devices.

6. Implementing the native plugin inside Unity3D.

Reproduce the following steps inside Unity3D:

  1. Open Unity3D and load your project.
  2. Create a “Plugins” folder with an “iOS” folder inside. Place the “Plugins” folder inside the “Assets” folder.
  3. Place the generated .a file inside the “iOS” folder together with the AppController subclass and plugin header ( MyNativeAppController.mm and MyNativePlugin.h )

Your native plugin is now ready to go!
Let’s look at the C# code to call our native plugin.

//connect to the extern method in Objective-C
[System.Runtime.InteropServices.DllImport("__Internal")]
extern static public void CallNativePlugin( string filename);

//Call the method from Unity3D.
CallNativePlugin( "this is a string");

//Voila!
// Native plugin has been called.

And that’s it!
To test it, build your project for iOS and test it on your device.

Happy coding 😀