This post will explore how to build an Android plugin for Unity 3D. No prior knowledge of Android Studio is assumed, every step of creating the Android .aar file is documented with images. The sample plugin created for this post will handle Android permissions.
API Level 23, Marshmallow changed the way requesting permissions works on Android. With API 23 and above, applications can query what permissions they have at runtime and ask for new permissions only when needed. Only ask for permissions that the application actually needs, asking for unnecessary permissions could result in an application being rejected.
This post was written for the following software versions:
Android Studio: 3.0.1
Unity 3D: 5.6.4p2
Building the aar
The first step in creating a native Android plugin is to create an Android Library, which is stored in an Android Archive (.aar) file. Android Libraries can be created using Android Studio. You can download and install Android Studio from Google here: https://developer.android.com/studio.
1) Launch Android Studio and select the “Start a new Android Studio project” option.
2) Name the project “PermissionHelperApp”. The name of the plugin is going to be “PermissionHelper”, but the project's name needs to be different.
3) Select the appropriate API level. This is going to be project dependent. The minimum API level for mobile vr applications is 21, but 23 is also a safe candidate. For now, select “API 21: Android 5.0 (Lollipop)”.
4) When prompted, select “Add no activity”. Since this is going to be a plugin, not a full application, there is no need to create any kind of default activity.
5) Wait for Android Studio to create the new project. This might take a while.
6a) When Android Studio is finished, switch to Project view. Do this by first clicking the “Project” tab on the left side of the IDE. Next, select “Project” from the dropdown menu on the top of the Project panel.
6b) Pay attention to the bottom of the editor, if there are any errors this is where they will be reported. On first run of Android Studio, this panel will likely contain a link to download the appropriate sdk for the api level selected.
7) There is a highlighted “App” folder when expanding the “PermissionHelperApp” project. This folder contains the Android application (.apk) that Android Studio created automatically. This application lives in the com.company.permissionhelperapp package, this is why the Application Name in step 2 had to be PermissionHelperApp instead of PermissionHelper.
Add a new module by right clicking on the “PermissionHelperApp” project, selecting “New”, then “Module”.
8) When prompted, select “Android Library” as the type for the new module.
9) Name the new module “PermissionHelper” and select an appropriate min API level. To keep things consistent, select the same min API level as in step 3, API 21: Android 5.0 (Lollipop)
10) In the project browser, expand the “PermissionHelperApp” project and expand the newly created “permissionhelper” module. Within this module, expand the “src” folder, then the “main” folder and the “java” folder. The last nested item should be: com.company.permissionhelper.
11) Right click, select “New” and “Java Class”
12) Name the new class “PermissionHelper”. This is the class that Unity will be interacting with.
13) There should be some empty default code in the newly created file already
14) Add two new member variables to the PermissionHelper class. One of the new variables should be the application Context, the other one should be the currently running Activity. Don't forget to import these classes.
package com.oculus.permissionhelper;
import android.app.Activity;
import android.content.Context;
public class PermissionHelper {
private Context mContext;
private Activity mActivity;
}
15) The constructor of the class should set both of these variables. Unity uses the same object as the applications context and activity. Pass in a single context and cast it to an activity.
package com.oculus.permissionhelper;
import android.app.Activity;
import android.content.Context;
public class PermissionHelper {
private Activity mActivity;
public PermissionHelper(Context context) {
mContext = context;
mActivity = (Activity)context;
}
}
16) Add the following functions to the PermissionHelper class:
CheckForPermission - This function takes a string, the permission name. It returns true if the permission has been granted to the application, otherwise false.
RequestPermission - This function takes a string, the permission name. It returns nothing. When called, an Android popup will display, asking the user for the specified permission.
Valid permission strings can be found here. The application context has a checkSelfPermission function, which can be used to check if the current application has been granted a specific permission. The application activity has a requestPermissions function which will show an android popup asking for the specified permission.
package com.oculus.permissionhelper;
import android.app.Activity;
import android.content.Context;
import android.Manifest;
import android.content.pm.PackageManager;
public class PermissionHelper {
private Context mContext;
private Activity mActivity;
public PermissionHelper(Context context) {
mContext = context;
mActivity = (Activity)context;
}
public boolean CheckForPermission(String permission) {
return mContext.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
public void RequestPermission(String permission) {
mActivity.requestPermissions(new String[]{permission},1024);
}
}
17) The above code is only valid for android API 23 and higher! If the project API level is set to anything less than 23, the above code will not compile. This is because the checkSelfPermission and requestPermissions functions only exist in API 23+.
In order to maintain backwards compatibility, these permission related functions need to be called through the ContextCompat and ActivityCompat compatibility layers. These classes contain static checkSelfPermission and requestPermissions functions which will not break when running on older versions of Android.
package com.oculus.permissionhelper;
import android.app.Activity;
import android.content.Context;
import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
public class PermissionHelper {
private Context mContext;
private Activity mActivity;
public PermissionHelper(Context context) {
mContext = context;
mActivity = (Activity)context;
}
public boolean CheckForPermission(String permission) {
// Only available with API Level 23+: return mContext.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
return ContextCompat.checkSelfPermission(mContext, permission) == PackageManager.PERMISSION_GRANTED;
}
public void RequestPermission(String permission) {
// Only available with API Level 23+: mActivity.requestPermissions(new String[]{permission},1024);
ActivityCompat.requestPermissions(mActivity, new String[]{permission},1024);
}
}
The above code is the final java code for the PermissionHelper plugin. For the compatibility code to work, applications need to link against android-support-v4, which should be located at:
<sdk-dir>/extras/android/m2repository/com/android/support/support-v4/23.0.0/support-v4-23.0.0.aar. This will be discussed in detail later in the Unity section of this post.
18) Now that the plugin code is finished, it's time to build the aar file. Click on the gradle tab on the right side of the editor to bring up the gradle build tools.
19) Within gradle, expand the PermissionHelperApp item project, then the :permissionhelper library, then the build group. Under the build group, double click on the build action.
20) Wait for Android Studio to finish building the aar files
21) In the project explorer, expand the build folder of the permissionhelper library. Under the build folder, expand the outputs and aar folders. One of the two files here is the aar file that will be used for the Unity plugin.
22) Right click the permissionhelper-release.aar file and select “Reveal in Finder” to quickly locate the file.
23) Rename permissionhelper-release.aar to permissionhelper.aar. Save this file somewhere, it will be used as the native permission plugin for Unity.
Manifest file
Android needs to know what permissions an application might ask for. Each permission that the application might ask for during its life time should be added to the application manifest file. The permission entry format for the manifest file looks like this:
Where PERMISSION_NAME would be replaced by the name of the requested android permission. A list of valid manifest permissions can be found here. All of the <uses-permission> tags are a direct child of the <manifest> tag. For example:
To create the permission plugin with Unity, first add permissionhelper.aar and support-v4-23.0.0.aar to the Plugins/Android directory.
support-v4-23.0.0.aar is located in the <sdk-dir>/extras/android/m2repository/com/android/support/support-v4/23.0.0/ directory.
Remember to add any potential permissions to the manifest file.
There needs to be some way to call the java code located in permissionhelper.aar. Create a new file, PermissionHelper.cs. Add three constant strings: the name of the activity, the name of the context, the full name of the PermissionHelper class.
using UnityEngine;
public static class PermissionHelper {
private static string ACTIVITY_NAME = "com.unity3d.player.UnityPlayer";
private static string CONTEXT = "currentActivity";
private static string PERMISSION_HELPER_CLASS = "com.oculus.permissionhelper.PermissionHelper";
Declare an AndroidJavaObject which will be used to call the native code. The InitIfNeeded function will initialize this variable the the current platform is android, and the permissionHelper variable is null.
Create a nested class, Permission. Add each permission string the application might need to this class. This class will serve as a convenience class for accessing these strings.
public static class Permissions {
public static string INTERNET = "android.permission.INTERNET";
public static string CAMERA = "android.permission.CAMERA";
public static string WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
};
Both the RequestPermission and CheckForPermission helper functions will use the private AndroidJavaObject to Call the java methods defined in permissionhelper.aar.
With the PermissionHelper class created, checking and asking for permissions can be one with one line of code each:
public class UIInteraction : MonoBehaviour {
public void SaveDataToDisk() {
if (PermissionHelper.CheckForPermission (PermissionHelper.Permissions.WRITE_EXTERNAL_STORAGE)) {
// Write actual data to disk
} else {
PermissionHelper.RequestPermission (PermissionHelper.Permissions.WRITE_EXTERNAL_STORAGE);
}
}
}
Wrap up
The plugin created in this blog can be used to ask for any kind of permission. Common permissions to ask for are internet access, disk write and microphone access.
By following the steps outlined, you should be able to create any kind of plugin which uses native android libraries / functionality.
Quarterly Developer Recap: Tracked Keyboard, Hand Gestures, WebXR PWAs and more
Unlock the latest updates for developers building 3D, 2D and web-based experiences for Horizon OS, including the new tracked keyboard, microgesture-driven locomotion, and more.
GDC 2025: Strategies and Considerations for Designing Incredible MR/VR Experiences
Dive into design and rendering tips from GDC 2025. Hear from the teams behind hit games like Batman: Arkham Shadow and Demeo and learn how you can make your mixed reality and VR games more enjoyable and accessible.
Accessiblity, All, Apps, Avatars, Design, GDC, Games, Hand Tracking, Optimization, Quest, Unity
GDC 2025: Emerging Opportunities in MR/VR on Meta Horizon OS
Discover some of the opportunities we shared at GDC 2025 to accelerate your development process, level up your skillset and expand your reach with Meta Horizon OS.