Steps to create a native Android plugin for Unity in Java using Android Studio – Part 2 (of 2)

In Part One of “Steps to create a native Android plugin for Unity in Java using Android Studio” of this blog post / tutorial, I described how to create a really simple ‘hello world’ method in Java using Android Studio that can be compiled into an Android Archive (.aar file) which can then be used as a native Android plugin in Unity.  In this post I’ll show how to add the plugin to Unity then how to call the static method we created in Java which returns a string and then displays it using a Unity Text UI component.

Please let me know if there are better ways of doing any this 🙂

Download Code for this

Assumptions:

  • I’m assuming that you already have Unity3D installed, if not, get it from here (Choose the most up to date version): Unity Downloads
  • I’m assuming you already have Android Studio and the relevant SDK’s installed?  If not you might want to start here and here.
  • I’m assuming you have a real Android device attached via USB or you are using the emulator and are used to building Unity Projects to your device. If not, you probably want to start here.
  • I’m assuming you have the .aar file that we created in part one, if not, please go back and follow part one.

Fire up Unity and create a new project…

  • Name the project is whatever you wish.

 

You should have a blank project once Unity has finished doing it’s thing…

 

Create a folder under Assets called Plugins then create a folder within that called Android.

This isn’t strictly required, but I think it helps anyone looking at the structure to know what these things are.

Drop the Android Archive (.aar) file we created in Part One into the Android folder….

 

In “Build Settings“, change the project type to “Android” and click “Switch Platform“…

 

You have to give the project a “Package Name” and set the Minimum API to the same as you chose for the Android Studio Project in Part One.

In this case I’ve chosen API Level 22 (as I target GearVR).

 

Add a Canvas along with a Text component  and position them in 2D space so that the text will display on the Android device screen.

I’ve also set the Unity Skybox to a solid colour and set the text to white font size to 64.

Check out the Github project for all the actual values for position etc if you need to.

 

Add the following files to the project…

I’ve put this in /Assets/HelloWorld.cs but feel free to put it elsewhere.

This is the code for the HelloWorld.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using UnityEngine;
using UnityEngine.UI;
 
public class HelloWorld : MonoBehaviour {
 
    Text textObj;
 
    void Start () {
 
        // Find the Text UI object attached to the game object this script is attached to
        textObj = gameObject.GetComponent();
 
        // Make the call using JNI to the Java Class and write out the response (or write 'Invalid Response From JNI' if there was a problem).
        textObj.text = CaptiveReality.Jni.Util.StaticCall("sayHello", "Invalid Response From JNI", "com.captivereality.texturehelper.HelloWorld");
    }
    
}
using UnityEngine;
using UnityEngine.UI;

public class HelloWorld : MonoBehaviour {

    Text textObj;

	void Start () {

        // Find the Text UI object attached to the game object this script is attached to
        textObj = gameObject.GetComponent();

        // Make the call using JNI to the Java Class and write out the response (or write 'Invalid Response From JNI' if there was a problem).
        textObj.text = CaptiveReality.Jni.Util.StaticCall("sayHello", "Invalid Response From JNI", "com.captivereality.texturehelper.HelloWorld");
    }
	
}

 

And Add this simple Jni Static Helper class that I made a Gist For at: JniUtil.cs

This is the code for the JniUtil.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
  Copyright 2017 Captive Reality Ltd
  
  Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is 
  hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 
  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
  FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
  Source: 
  Description: 
  A very simple static helper (for Unity) that you can use to call a static Java method in a Java class using Jni
  
  Examples: 
  int result = CaptiveReality.Jni.Util.StaticCall("getAMethodWhichReturnsInt", 1, "com.yourandroidlib.example.ClassName");
  string result = CaptiveReality.Jni.Util.StaticCall("getAMethodWhichReturnsString", "UNKNOWN", "com.yourandroidlib.example.ClassName");
    
*/
 
using UnityEngine;
 
namespace CaptiveReality.Jni
{
    class Util
    {
        /// <summary>
        /// StaticCall - Call a static Java method in a class using Jni
        /// </summary>
        /// <typeparam name="T">The return type of the method in the class you are calling</typeparam>
        /// <param name="methodName">The name of the method you want to call</param>
        /// <param name="defaultValue">The value you want to return if there was a problem</param>
        /// <param name="androidJavaClass">The name of the Package and Class eg, packagename.myClassName or com.yourandroidlib.example.ClassName</param>
        /// <returns>Generic</returns>
        public static T StaticCall(string methodName, T defaultValue, string androidJavaClass)
        {
            T result;
 
            // Only works on Android!
            if (Application.platform != RuntimePlatform.Android)
            {
                return defaultValue;
            }
 
            try
            {
                using (AndroidJavaClass androidClass = new AndroidJavaClass(androidJavaClass))
                {
                    if (null != androidClass)
                    {
                        result = androidClass.CallStatic(methodName);
                    }
                    else
                    {
                        result = defaultValue;
                    }
 
                }
            }
            catch (System.Exception ex)
            {
                // If there is an exception, do nothing but return the default value
                // Uncomment this to see exceptions in Unity Debug Log....
                // UnityEngine.Debug.Log(string.Format("{0}.{1} Exception:{2}", androidJavaClass, methodName, ex.ToString() ));
                return defaultValue;
            }
 
            return result;
 
        }
 
    }
}
/*
  Copyright 2017 Captive Reality Ltd
  
  Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is 
  hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 
  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
  FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
  Source: 
  Description: 
  A very simple static helper (for Unity) that you can use to call a static Java method in a Java class using Jni
  
  Examples: 
  int result = CaptiveReality.Jni.Util.StaticCall("getAMethodWhichReturnsInt", 1, "com.yourandroidlib.example.ClassName");
  string result = CaptiveReality.Jni.Util.StaticCall("getAMethodWhichReturnsString", "UNKNOWN", "com.yourandroidlib.example.ClassName");
    
*/

using UnityEngine;

namespace CaptiveReality.Jni
{
    class Util
    {
        /// <summary>
        /// StaticCall - Call a static Java method in a class using Jni
        /// </summary>
        /// <typeparam name="T">The return type of the method in the class you are calling</typeparam>
        /// <param name="methodName">The name of the method you want to call</param>
        /// <param name="defaultValue">The value you want to return if there was a problem</param>
        /// <param name="androidJavaClass">The name of the Package and Class eg, packagename.myClassName or com.yourandroidlib.example.ClassName</param>
        /// <returns>Generic</returns>
        public static T StaticCall(string methodName, T defaultValue, string androidJavaClass)
        {
            T result;

            // Only works on Android!
            if (Application.platform != RuntimePlatform.Android)
            {
                return defaultValue;
            }

            try
            {
                using (AndroidJavaClass androidClass = new AndroidJavaClass(androidJavaClass))
                {
                    if (null != androidClass)
                    {
                        result = androidClass.CallStatic(methodName);
                    }
                    else
                    {
                        result = defaultValue;
                    }

                }
            }
            catch (System.Exception ex)
            {
                // If there is an exception, do nothing but return the default value
                // Uncomment this to see exceptions in Unity Debug Log....
                // UnityEngine.Debug.Log(string.Format("{0}.{1} Exception:{2}", androidJavaClass, methodName, ex.ToString() ));
                return defaultValue;
            }

            return result;

        }

    }
}

This is just a really simple Generic static to return a result from a Java static method.

 

Attach the “HelloWorld.cs” script to the Text GameObject component….

 

Now build the project “Build & Run“…

Hopefully you have a real Android Device attached or are building to the Emulator

 

With a bit of luck this should be the output you see on your Android Device (or Emulator)….

 

I’ll be trying to add to this project soon. 🙂

I Hope this helps someone to get up and running fast with Android Plugins for Unity as I found it difficult initially to put all the pieces together, which is annoying when you just want to get on an code.

Download Code for this

 

  4 comments for “Steps to create a native Android plugin for Unity in Java using Android Studio – Part 2 (of 2)

  1. Megabro
    December 18, 2017 at 12:19 pm

    Thanks pal! I scoured the net for help with making this in Android Studio. Your guide is by far the best and most up-to-date (IMO)

  2. Megabro
    December 18, 2017 at 4:25 pm

    I followed well all way til the end. But when I get to JniUtils.cs , Visual Studio doesnt recognize T. It says “Type or namespace T could not be found are you missing a using directive”

    • admin
      September 11, 2018 at 2:29 pm

      Hi… It’s JniUtil.cs (no ‘s’ in there). Links to the source for that are in the article (and here… https://gist.github.com/markcastle/a1530efd5278607862fec09df89e59db )
      Just drop that into the project and hopefully you should be good to go 🙂
      Let me know if I’ve misunderstood and I’ll try to help.
      Cheers – Mark

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.