Embedding Unity App inside Native Android application
While unity provides an android build-out of the box, there are scenarios where we would like to do a part unity and part android kind of application. The typical use case is where you would like to use Unity’s capability of 3D rendering and AR inside your e-commerce application which is built using Android Java SDK.
Communicating to the Unity app from an android application is possible via Android’s Intents and passing data to them. If the need is to constantly communicate with the Unity App then the intent-based approach would be a limitation since you can pass the data only once.
One solution to continuously communicate between the android app and the unity app is to wrap the Unity app as an android Fragment and then you can pass and receive data to and fro. This is done 5 steps,
- In the Unity application, implement the data integration points as methods
- Export Unity application as Android Library
- Import the exported library as a module into your android project
- Write a custom Fragment class which will wrap UnityActivity inside a Fragment
- Use the custom fragment in Android Activity
Step 1: Implementing integration points in Unity
Create a Script called DataExchanger.cs and attach it to the Canvas object
The first integration point is the “PassDataToAndroid” method, where we get the Unity Activity’s Java handle and call a static method with the data we indent to transfer.
The second integration point is a placeholder method named “ShowMessage” with a parameter that will be passed from android. This method may decide what to do with the received data. In this sample, I decided to just display it in an input field on the canvas.
Step 2: Export Unity Application as Android Library
Before exporting the application, the following settings need to be changed in Build settings
a. Confirm the target platform is Android
b. Build System is Gradle
c. Export Project is checked
Goto Player Settings
a. Change Scripting Background to IL2CPP
b. Select ARM64 in the Target architectures
Once these changes are made, Click “Export” and select a folder where the android project need to be exported.
Open the exported project in Android Studio, we need to the following changes to the exported build.gradle file
Change this line
apply plugin: 'com.android.application'
to
apply plugin: 'com.android.library'
find the line which has the applicationId and delete the line from gradle
applicationId '<package name>'
if there is a bundle section like the one below
bundle {
language {
enableSplit = false
}
density {
enableSplit = false
}
abi {
enableSplit = true
}
comment it out or delete it from the build.gradle
After the above steps, save build.gradle and build the project. This will create an aar file in the build output folder. Make a note of this AAR file path, we will be using this in the next step.
Step 3: Import the exported library as a module into your android project
Open the existing android project (or create a new one)
Import the AAR as a new module into your android project
Once the AAR library is imported as a module into the project, in the build.gradle (for the app) in the dependencies section add the imported module
dependencies {
implementation project(":<nameofaarlibrary>")
implementation fileTree(dir: 'libs', include: ['*.jar'])
In the AndroidManifest.xml, add the highlighted lines if they don’t exist
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.thoughtworks.embeddedunitytest">
<application
android:allowBackup="true"
tools:replace="android:icon,android:theme"
android:icon="@mipmap/ic_launcher"
In settings.gradle, make sure that the include has the aar module
include ':app', ':<aarmodulename>'
Step 4: Write custom Fragment wrapper class for UnityActivity
Add a new UnityFragment class as shown below,
The key is the onCreateView method which will instantiate our UnityPlayer activity in the library and fit it inside a frame layout. Now our application is available to be used as a Fragment in the project.
When we would like to pass the data to Unity, at any point in time you can call
UnityPlayer.UnitySendMessage("<GameObject>", "<Method>",<string value>);
This will call the method in the specified GameObject with the given string value.
The pain point is that every time when we update our Unity project, the AAR library export (step 3) needs to be done from scratch. You can automate this in your CI build server though.
The entire sample project is available in this Github Project.