igorpavlov
igorpavlov

Reputation: 3626

Unity GearVR get rid of "requesting permission..."

Status: not solved yet

Problem

Once I build and install an app with GearVR it asks by default:

XXX is requesting permission to access photos, media and files on your device. Allow?

Allow / Deny

I don't need my app to access any of those above. How can I get rid of this programmatically?

Edit 1

It seems that Unity automatically adds READ_EXTERNAL_STORAGE to any build for some reason. Stripping out the permission doesn't help in newer versions of Unity as the build fails with the message:

Unable to merge android manifests...

Edit 2

The OVRPlugin causes this issue and at the moment.

https://forum.unity3d.com/threads/how-to-remove-android-permission-read_external_storage.429369/

Unity forums say it is unlikely to fix. Maybe there are still some workarounds?

Edit 3

Oculus is working on it, we should receive a fix in February

https://forums.oculus.com/developer/discussion/42465/is-android-permission-read-external-storage-a-must-when-using-unity#latest

Upvotes: 2

Views: 1070

Answers (1)

Kardux
Kardux

Reputation: 2157

I stumble upon this some time ago and still not sure why Unity builds ask for those permissions. Anyway to get rid of them you can use an editor script as a workaround:

protected void BuildAPKCustom(string buildPath)
{
    bool manifestFileExists = false;
    if(File.Exists(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml")))
    {
        manifestFileExists = true;
        File.Copy(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"), Path.Combine(Application.dataPath, "Plugins/Android/tmpManifestFile.xml"));
        File.Delete(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"));
    }

    string[] levels = new string[EditorSceneManager.sceneCount];
    for (int i = 0; i < levels.Length; i++)
    {
        levels[i] = EditorSceneManager.GetSceneAt(i).path;
    }
    BuildPipeline.BuildPlayer(levels, buildPath, BuildTarget.Android, BuildOptions.None);

    XNamespace android = "http://schemas.android.com/apk/res/android";
    string generatedXMLFilePath = Path.Combine(Application.dataPath, "../Temp/StagingArea/AndroidManifest.xml");
    XDocument doc = XDocument.Load(generatedXMLFilePath);
    IEnumerable<XElement> permissionElements = doc.Root.Elements("uses-permission");
    foreach(XElement permission in permissionElements)
    {
        int potentialIndex = PERMISSIONS_NAMES_TO_DELETE.IndexOf(permission.Attribute(android + "name").Value.Replace("android.permission.", ""));
        if(potentialIndex >= 0)
        {
            UnityEngine.Debug.Log("Permission deleted : " + PERMISSIONS_NAMES_TO_DELETE[potentialIndex]);
            permission.Remove();
        }
    }

    XElement overwritenPermission;
    for(int i = 0; i < PERMISSIONS_NAMES_TO_DELETE.Length; i++)
    {
        overwritenPermission = new XElement("uses-permission");
        overwritenPermission.Add(new XAttribute(android + "name", "android.permission." + PERMISSIONS_NAMES_TO_DELETE[i]));
        overwritenPermission.Add(new XAttribute(android + "maxSdkVersion", "18"));
        doc.Element("manifest").Add(overwritenPermission);
    }

    if(!Directory.Exists(Path.Combine(Application.dataPath, "Plugins/Android")))
    {
        Directory.CreateDirectory(Path.Combine(Application.dataPath, "Plugins/Android"));
    }

    doc.Save(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"));

    BuildPipeline.BuildPlayer(levels, buildPath, BuildTarget.Android, BuildOptions.None);

    if(manifestFileExists)
    {
        File.Delete(Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"));
        File.Copy(Path.Combine(Application.dataPath, "Plugins/Android/tmpManifestFile.xml"), Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"));
        File.Delete(Path.Combine(Application.dataPath, "Plugins/Android/tmpManifestFile.xml"));
    }

    Process.Start(Path.GetDirectoryName(buildPath));
}

(PERMISSIONS_NAMES_TO_DELETE being a string[] of the permissions names to delete. To get the permissions names list you can look here)

What it does is:

  • get the previous AndroidManifest.xml file (if it exists) in /Android/Plugins/ folder, copy it to a temporary one and delete it
  • perform a first build to let Unity generate an AndroidManifest.xml file on his own
  • edit the manifest to "delete" unnecessary permissions
  • save the edited manifest to /Android/Plugins/
  • perform a second build with a correctly set manifest

The idea behind the permission deletion is to set the maximum API level to such a lower level, the permissions will not be usable (please note the permission MUST exists at this API level).

Hope this helps,

Upvotes: 1

Related Questions