UnityでOculus Go/Questアプリをビルドする時に不要なパーミッションを取り除く

# はじめに

UnityでOculus Go/Questアプリを作るときに[Oculus Integration](https://assetstore.unity.com/packages/tools/integration/oculus-integration-82022)を導入するとOculus Lipsyncがマイクを使うのでAndroidManifest.xmlにマイク権限のパーミッションが付与されます。
この権限を付与したくない場合は以下のように該当スクリプトを削除する方法があります。

* [Unity製Oculus Go用アプリが「マイクの権限を削除してください」とリジェクトされた時の対処法【Unity】【Oculus Go】【リジェクト】](http://kan-kikuchi.hatenablog.com/entry/Oculus_Microphone_Reject)
* [Oculus GO アプリで、マイクのパーミッションが出ないようにする](https://littlewing.hatenablog.com/entry/2018/09/04/170626)

ですが該当スクリプトが見付けられなかったりうまく除去できない事もあります。そんな時はGradleでビルドする直前にコールバックされる`IPostGenerateGradleAndroidProject`を利用するとAndroidManifext.xmlからパーミッションを除去する事ができます。

* [IPostGenerateGradleAndroidProject](https://docs.unity3d.com/ScriptReference/Android.IPostGenerateGradleAndroidProject.html)
* [java - Use custom Manifest file and permission in Unity?](https://stackoverflow.com/questions/43293173/use-custom-manifest-file-and-permission-in-unity)
* [【Unity】ハードウェアアクセラレーションが有効にならない、AndroidManifestを書き換えても無効になってしまう問題の解決](https://qiita.com/matsu_shita_ido/items/55e9feca9f79a3570f15)

# マイク権限を取り除くコールバック

stackoverflowのスクリプトがそのまま使えるのでちょっと変更してマイク権限を取り除くコールバックです。
変更した部分だけコメントを書いています。XPathとC#でXMLの操作が分かれば特に難しくないと思います。

```cs:Assets/Editor/ModifyUnityAndroidAppManifestSample.cs
#if UNITY_ANDROID
using System.IO;
using System.Text;
using System.Xml;
using UnityEditor.Android;

public class ModifyUnityAndroidAppManifestSample : IPostGenerateGradleAndroidProject
{

	public void OnPostGenerateGradleAndroidProject(string basePath)
	{
		var androidManifest = new AndroidManifest(GetManifestPath(basePath));

		// マイク権限を取り除く
		androidManifest.RemoveMicrophonePermission();

		androidManifest.Save();
	}

	public int callbackOrder => 1;

	private string _manifestFilePath;

	private string GetManifestPath(string basePath)
	{
		if (string.IsNullOrEmpty(_manifestFilePath))
		{
			var pathBuilder = new StringBuilder(basePath);
			pathBuilder.Append(Path.DirectorySeparatorChar).Append("src");
			pathBuilder.Append(Path.DirectorySeparatorChar).Append("main");
			pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml");
			_manifestFilePath = pathBuilder.ToString();
		}
		return _manifestFilePath;
	}
}

internal class AndroidXmlDocument : XmlDocument
{
	private string m_Path;
	protected XmlNamespaceManager nsMgr;
	public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android";

	public AndroidXmlDocument(string path)
	{
		m_Path = path;
		using (var reader = new XmlTextReader(m_Path))
		{
			reader.Read();
			Load(reader);
		}
		nsMgr = new XmlNamespaceManager(NameTable);
		nsMgr.AddNamespace("android", AndroidXmlNamespace);
	}

	public string Save()
	{
		return SaveAs(m_Path);
	}

	public string SaveAs(string path)
	{
		using (var writer = new XmlTextWriter(path, new UTF8Encoding(false)))
		{
			writer.Formatting = Formatting.Indented;
			Save(writer);
		}
		return path;
	}
}

internal class AndroidManifest : AndroidXmlDocument
{
	private readonly XmlElement ApplicationElement;

	public AndroidManifest(string path) : base(path)
	{
		ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
	}

	private XmlAttribute CreateAndroidAttribute(string key, string value)
	{
		var attr = CreateAttribute("android", key, AndroidXmlNamespace);
		attr.Value = value;
		return attr;
	}

	// マイク権限を取り除く
	public void RemoveMicrophonePermission()
	{
		var microphones = new[]
		{
			"//uses-permission[@android:name='android.permission.RECORD_AUDIO']",
			"//uses-feature[@android:name='android.hardware.microphone']"
		};
		var manifest = SelectSingleNode("/manifest");
		if (manifest == null)
		{
			return;
		}

		foreach (var microphone in microphones)
		{
			var node = manifest.SelectSingleNode(microphone, nsMgr);
			if (node != null)
			{
				manifest.RemoveChild(node);
			}
		}
	}
}
#endif
```

これでUnityが自動で付与する権限を削除できました。アプリをビルドして生成される`[ProjectFolder]/Temp/gradleOut/src/main/AndroidManifext.xml`からもマイク権限が削除されていると思います。

ですがAARに入っているAndroidManifest.xmlからマージされるノードなどは一工夫しなければ削除できませんので別の記事に書きたいと思います。

# 参考リンク

* [Unity製Oculus Go用アプリが「マイクの権限を削除してください」とリジェクトされた時の対処法【Unity】【Oculus Go】【リジェクト】](http://kan-kikuchi.hatenablog.com/entry/Oculus_Microphone_Reject)
* [Oculus GO アプリで、マイクのパーミッションが出ないようにする](https://littlewing.hatenablog.com/entry/2018/09/04/170626)
* [IPostGenerateGradleAndroidProject](https://docs.unity3d.com/ScriptReference/Android.IPostGenerateGradleAndroidProject.html)
* [java - Use custom Manifest file and permission in Unity?](https://stackoverflow.com/questions/43293173/use-custom-manifest-file-and-permission-in-unity)
* [【Unity】ハードウェアアクセラレーションが有効にならない、AndroidManifestを書き換えても無効になってしまう問題の解決](https://qiita.com/matsu_shita_ido/items/55e9feca9f79a3570f15)