260 lines
10 KiB
C#
260 lines
10 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using UnityEditor;
|
|
using UnityEditor.Build.Reporting;
|
|
using UnityEditor.XR.OpenXR.Features;
|
|
using UnityEngine.XR.OpenXR;
|
|
using UnityEngine.XR.OpenXR.Features;
|
|
|
|
|
|
namespace Unity.XR.OpenXR.Features.PICOSupport
|
|
{
|
|
internal class PICOModifyAndroidManifest : OpenXRFeatureBuildHooks
|
|
{
|
|
public override int callbackOrder => 1;
|
|
public override Type featureType => typeof(PICOFeature);
|
|
protected override void OnPreprocessBuildExt(BuildReport report) { }
|
|
protected override void OnPostGenerateGradleAndroidProjectExt(string path)
|
|
{
|
|
var androidManifest = new AndroidManifest(GetManifestPath(path));
|
|
androidManifest.AddPICOMetaData(path);
|
|
androidManifest.Save();
|
|
}
|
|
protected override void OnPostprocessBuildExt(BuildReport report) { }
|
|
private string _manifestFilePath;
|
|
private string GetManifestPath(string basePath)
|
|
{
|
|
if (!string.IsNullOrEmpty(_manifestFilePath)) return _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;
|
|
}
|
|
private 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;
|
|
}
|
|
}
|
|
private class AndroidManifest : AndroidXmlDocument
|
|
{
|
|
private readonly XmlElement ApplicationElement;
|
|
private readonly XmlElement ManifestElement;
|
|
public AndroidManifest(string path) : base(path)
|
|
{
|
|
ManifestElement = SelectSingleNode("/manifest") as XmlElement;
|
|
ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
|
|
}
|
|
private XmlAttribute CreateOrUpdateAndroidAttribute(string key, string value)
|
|
{
|
|
XmlAttribute attr = CreateAttribute("android", key, AndroidXmlNamespace);
|
|
attr.Value = value;
|
|
return attr;
|
|
}
|
|
private void CreateOrUpdateAndroidPermissionData(string name)
|
|
{
|
|
XmlNodeList nodeList = ManifestElement.SelectNodes("uses-permission");
|
|
foreach (XmlNode node in nodeList)
|
|
{
|
|
if (node != null)
|
|
{
|
|
// Update existing nodes
|
|
if (node.Attributes != null && name.Equals(node.Attributes[0].Value))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create new node
|
|
var md = ManifestElement.AppendChild(CreateElement("uses-permission"));
|
|
md.Attributes.Append(CreateOrUpdateAndroidAttribute("name", name.ToString()));
|
|
}
|
|
|
|
private void DeleteAndroidPermissionData(string name)
|
|
{
|
|
XmlNodeList nodeList = ManifestElement.SelectNodes("uses-permission");
|
|
foreach (XmlNode node in nodeList)
|
|
{
|
|
if (node != null)
|
|
{
|
|
// Delete existing nodes
|
|
if (node.Attributes != null && name.Equals(node.Attributes[0].Value))
|
|
{
|
|
node.ParentNode?.RemoveChild(node);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CreateOrUpdateAndroidMetaData(string name, string value)
|
|
{
|
|
XmlNodeList nodeList = ApplicationElement.SelectNodes("meta-data");
|
|
foreach (XmlNode node in nodeList)
|
|
{
|
|
if (node != null)
|
|
{
|
|
// Update existing nodes
|
|
if (node.Attributes != null && name.Equals(node.Attributes[0].Value))
|
|
{
|
|
node.Attributes[0].Value = name;
|
|
node.Attributes[1].Value = value;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create new node
|
|
var md = ApplicationElement.AppendChild(CreateElement("meta-data"));
|
|
md.Attributes.Append(CreateOrUpdateAndroidAttribute("name", name.ToString()));
|
|
md.Attributes.Append(CreateOrUpdateAndroidAttribute("value", value.ToString()));
|
|
}
|
|
|
|
private void DeleteAndroidMetaData(string name)
|
|
{
|
|
XmlNodeList nodeList = ApplicationElement.SelectNodes("meta-data");
|
|
foreach (XmlNode node in nodeList)
|
|
{
|
|
if (node != null)
|
|
{
|
|
// Delete existing nodes
|
|
if (node.Attributes != null && name.Equals(node.Attributes[0].Value))
|
|
{
|
|
node.ParentNode?.RemoveChild(node);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void AddPICOMetaData(string path)
|
|
{
|
|
CreateOrUpdateAndroidMetaData("pvr.app.type", "vr");
|
|
CreateOrUpdateAndroidMetaData("pvr.sdk.version", "Unity OpenXR "+PICOFeature.SDKVersion);
|
|
CreateOrUpdateAndroidMetaData("pxr.sdk.version_code", "5800");
|
|
|
|
if (PICOProjectSetting.GetProjectConfig().isHandTracking)
|
|
{
|
|
CreateOrUpdateAndroidPermissionData("com.picovr.permission.HAND_TRACKING");
|
|
CreateOrUpdateAndroidMetaData("handtracking", "1");
|
|
}
|
|
else
|
|
{
|
|
DeleteAndroidPermissionData("com.picovr.permission.HAND_TRACKING");
|
|
DeleteAndroidMetaData("handtracking");
|
|
}
|
|
|
|
if (PICOProjectSetting.GetProjectConfig().isEyeTracking)
|
|
{
|
|
CreateOrUpdateAndroidPermissionData("com.picovr.permission.EYE_TRACKING");
|
|
CreateOrUpdateAndroidMetaData("picovr.software.eye_tracking", "1");
|
|
CreateOrUpdateAndroidMetaData("eyetracking_calibration", PICOProjectSetting.GetProjectConfig().isEyeTrackingCalibration ? "true" : "false");
|
|
}
|
|
else
|
|
{
|
|
DeleteAndroidPermissionData("com.picovr.permission.EYE_TRACKING");
|
|
DeleteAndroidMetaData("picovr.software.eye_tracking");
|
|
DeleteAndroidMetaData("eyetracking_calibration");
|
|
}
|
|
|
|
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
|
|
bool mrPermission = false;
|
|
|
|
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
|
|
{
|
|
|
|
if (feature is PICOSceneCapture)
|
|
{
|
|
if (feature.enabled)
|
|
{
|
|
CreateOrUpdateAndroidMetaData("enable_scene_anchor", "1");
|
|
|
|
mrPermission = true;
|
|
}
|
|
else
|
|
{
|
|
DeleteAndroidMetaData("enable_scene_anchor");
|
|
}
|
|
}
|
|
|
|
if (feature is PICOSpatialAnchor)
|
|
{
|
|
if (feature.enabled)
|
|
{
|
|
CreateOrUpdateAndroidMetaData("enable_spatial_anchor", "1");
|
|
mrPermission = true;
|
|
}
|
|
else
|
|
{
|
|
DeleteAndroidMetaData("enable_spatial_anchor");
|
|
}
|
|
}
|
|
|
|
if (feature is PICOSpatialMesh)
|
|
{
|
|
if (feature.enabled)
|
|
{
|
|
CreateOrUpdateAndroidMetaData("enable_mesh_anchor", "1");
|
|
mrPermission = true;
|
|
}
|
|
else
|
|
{
|
|
DeleteAndroidMetaData("enable_mesh_anchor");
|
|
}
|
|
}
|
|
|
|
}
|
|
if (PICOProjectSetting.GetProjectConfig().MRSafeguard)
|
|
{
|
|
CreateOrUpdateAndroidMetaData("enable_mr_safeguard", PICOProjectSetting.GetProjectConfig().MRSafeguard ? "1" : "0");
|
|
}
|
|
else
|
|
{
|
|
DeleteAndroidMetaData("enable_mr_safeguard");
|
|
}
|
|
|
|
if (mrPermission)
|
|
{
|
|
CreateOrUpdateAndroidPermissionData("com.picovr.permission.SPATIAL_DATA");
|
|
}
|
|
else
|
|
{
|
|
DeleteAndroidPermissionData("com.picovr.permission.SPATIAL_DATA");
|
|
}
|
|
|
|
CreateOrUpdateAndroidMetaData("pvr.app.splash", PICOProjectSetting.GetProjectConfig().GetSystemSplashScreen(path));
|
|
}
|
|
}
|
|
}
|
|
} |