So I’m ready to release an app to Google Play but it’s showing up as requiring permissions I do not want. The app is targeted at children and parents, so it’s very important that we include only the permissions necessary. (It’s also a requirement not to include position tracking, which is one of the problem permissions, if you want to have the “everyone” rating.)
I’ve overridden the Android manifest file successfully by placing it under Plugins/Android/AndroidManifest.xml. This appears to work, and I can see my changes in the manifest Unity is using by checking temp/stagingarea/AndroidManifest.xml after running a build.
However, Unity also appends several permission requirements to this file. In my case, they are:
We don’t need these permissions for our app. I’ve heard that perhaps Unity is automatically adding permissions based on code references to these features? I’m not sure if this is true, but if so it’s very problematic for us. We use several different 3rd-party code libraries with optional features that aren’t actually used in the app. Hunting through such libraries and removing the bits we don’t use is not a reasonable option for us.
So the question is: How can I prevent Unity from adding these unwanted permissions to the manifest file on build?
We had the same issue with Unity adding permissions to our manifest that we did not need/want. In our case a plugin we’re using (Fabric) was referencing the Microphone API of Unity, making Unity add the RECORD_AUDIO permission to our manifest.
Now, the way we solved this was to add the RECORD_AUDIO manifest to our own manifest in the Plugins/Android folder, but also specify a maxSdkVersion for the permission that’s lower than the minSdkVersion of our app;
This makes Unity use that permission in the created manifest, but since the maxSdkVersion is set to 1, users do not have to give that permission when installing because the minSdkVersion of the app i higher.
Find “Input.location” in all files, if any .cs file contains this code, uses-permission android:name=“android.permission.ACCESS_FINE_LOCATION” will be added automatically when building apk.Delete all related files, this issue will be fixed.
One possible solution which appears to work is to export a Google Android project instead of building directly from Unity. Then one can modify the manifest (again) in Google’s environment, build and sign.
This does accomplish what I need, but it creates a somewhat hellish workflow for creating publishable builds. It also required learning a set of tools I didn’t need for any particular reason other than working around a problem Unity seems to have created.
Hi I’ve just found a nice soultion to the manifest permission problem.
Build an .apk file as always. Don’t worry about manifest file.
Deploy the app to the android device.
Download permission manager from Google Play store. In my case this was Advanced Permission Manager. Free version will do good. You don’t have to root the device.
Remove permissions from apk fie and push th Save and Install button.
Voila! You have New.apk file in PermMaster folder on the device - this is your apk file without unwanted permissions.
What worked for me was - I found that there are multiple androidmanifest.xml. Unity is merging them on compile. Look for other manifests and edit them… if you have them and they have additional permissions.
They could be in plugins and other stuff that may need permissions.
Careful with deleting stuff. Unity may not like and say that it cant merge manifests.
I’ve solved it in a very simple way, just compile this c# code into a console application, pass it 2 parameters; source AndroidManifest.xml, and Unity project path.
Make sure it’s running during your build. It will detect Unity’s modifications, and overwrite it with your own AndroidManifest.xml BEFORE it’s built into the APK.
using System;
using System.IO;
using System.Linq;
using System.Threading;
namespace OverrideManifest
{
class Program
{
static void Main( string[] args )
{
if ( args.Length == 2 )
{
string sourceManifestPath = args[0];
string destManifestPath = args[1] + "/Temp/StagingArea/AndroidManifest.xml";
if ( File.Exists( sourceManifestPath ) )
{
byte[] file1Bytes = File.ReadAllBytes( sourceManifestPath );
Console.WriteLine( "Waiting for manifest to change.... ESC to Quit
Digging into the obfuscated code, I found that Unity reads all of the permissions from the manifest and checks if they are granted. If they are not, it requests them. It doesn’t make sense, but it’s what they do. Here’s the offending code.
public final void a(Activity var1, Runnable var2) {
if(var1 != null) {
PackageManager var3 = var1.getPackageManager();
try {
ActivityInfo var4 = var3.getActivityInfo(var1.getComponentName(), 128);
ApplicationInfo var5 = var3.getApplicationInfo(var1.getPackageName(), 128);
if(a(var4) || a(var5)) {
var2.run();
return;
}
} catch (Exception var11) {
;
}
try {
PackageInfo var12;
if((var12 = var3.getPackageInfo(var1.getPackageName(), 4096)).requestedPermissions == null) {
var12.requestedPermissions = new String[0];
}
LinkedList var15 = new LinkedList();
String[] var13;
int var6 = (var13 = var12.requestedPermissions).length;
for(int var7 = 0; var7 < var6; ++var7) {
String var8 = var13[var7];
try {
//if permission is dangerous AND it's not granted, add to list
if((var3.getPermissionInfo(var8, 128).protectionLevel & 1) != 0 && var1.checkCallingOrSelfPermission(var8) != 0) {
var15.add(var8);
}
} catch (NameNotFoundException var9) {
e.Log(5, "Failed to get permission info for " + var8 + ", manifest likely missing custom permission declaration");
e.Log(5, "Permission " + var8 + " ignored");
}
}
if(var15.isEmpty()) {
var2.run();
} else {
//starts a fragment that requests permissions
g var14 = new g(var2);
Bundle var16;
(var16 = new Bundle()).putStringArray("PermissionNames", (String[])var15.toArray(new String[0]));
var14.setArguments(var16);
FragmentTransaction var17;
(var17 = var1.getFragmentManager().beginTransaction()).add(0, var14);
var17.commit();
}
} catch (Exception var10) {
e.Log(6, "Unable to query for permission: " + var10.getMessage());
}
}
}
But there are good news, we can block Unity from requesting the permission! The only place we can interfere with this logic is checkCallingOrSelfPermission. So, if you are absolutely positive that you don’t need a given permission, in your Activity you can return PERMISSION_GRANTED, either for all permissions or only for those you don’t need. In my case, I didn’t need any permission
@Override
public int checkCallingOrSelfPermission(String permission) {
/*
UGLY HACK!!
Always report to Unity that we have the permission. For now we don't seem to use it so it's not
a problem, but if some edge case does use it, the app will crash.
Or if Unity changes something in their side, we can also have problems.
*/
return PackageManager.PERMISSION_GRANTED;
}
I don’t even know which Unity version I’m using (I’m not a Unity developer), but I hope this works in modern versions.
Definitely go to:
C:\Program Files [or Program Files (x86)\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Apk
open the AndroidManifest and add the following inside the Activity section:
Note that all this does is tell Unity ‘hey, don’t ask for the permissions until you really need to use them’. If they’re unneeded, it should never ask for them!