/**************************************************************************** * Copyright 2019 Nreal Techonology Limited.All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal { using System.Text; using System.Xml; /// An android XML document. internal class AndroidXmlDocument : XmlDocument { /// Full pathname of the file. protected string m_Path; /// Manager for name space. protected XmlNamespaceManager nameSpaceManager; /// The android XML namespace. public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android"; /// The android tools XML namespace. public readonly string AndroidToolsXmlNamespace = "http://schemas.android.com/tools"; /// Constructor. /// Full pathname of the file. public AndroidXmlDocument(string path) { m_Path = path; using (var reader = new XmlTextReader(m_Path)) { reader.Read(); Load(reader); } nameSpaceManager = new XmlNamespaceManager(NameTable); nameSpaceManager.AddNamespace("android", AndroidXmlNamespace); } /// Gets the save. /// A string. public string Save() { return SaveAs(m_Path); } /// Saves as. /// Full pathname of the file. /// A string. public string SaveAs(string path) { using (var writer = new XmlTextWriter(path, new UTF8Encoding(false))) { writer.Formatting = Formatting.Indented; Save(writer); } return path; } } /// A list of the android. internal class AndroidManifest : AndroidXmlDocument { /// Element describing the application. private readonly XmlElement ApplicationElement; /// Constructor. /// Full pathname of the file. public AndroidManifest(string path) : base(path) { ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement; } /// Creates android attribute. /// The key. /// The value. /// (Optional) The name. /// The new android attribute. private XmlAttribute CreateAndroidAttribute(string key, string value, string name = "android") { XmlAttribute attr; if (name.Equals("tools")) { attr = CreateAttribute(name, key, AndroidToolsXmlNamespace); attr.Value = value; } else { attr = CreateAttribute(name, key, AndroidXmlNamespace); attr.Value = value; } return attr; } /// Gets activity with launch intent. /// The activity with launch intent. internal XmlNode GetActivityWithLaunchIntent() { return SelectSingleNode("/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " + "intent-filter/category/@android:name='android.intent.category.LAUNCHER']", nameSpaceManager); } /// Gets activity with information intent. /// The activity with information intent. internal XmlNode GetActivityWithInfoIntent() { return SelectSingleNode("/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " + "intent-filter/category/@android:name='android.intent.category.INFO']", nameSpaceManager); } /// Sets external storage. /// True to flag. internal void SetExternalStorage(bool flag) { var activity = SelectSingleNode("/manifest/application"); var rightapplicationData = SelectSingleNode("/manifest/application[@android:requestLegacyExternalStorage='true']", nameSpaceManager); if (flag) { if (rightapplicationData == null) { XmlAttribute newAttribute = CreateAndroidAttribute("requestLegacyExternalStorage", "true"); activity.Attributes.Append(newAttribute); } } else { if (rightapplicationData != null) { activity.Attributes.RemoveNamedItem("android:requestLegacyExternalStorage"); } } } /// Sets camera permission. internal void SetCameraPermission() { var manifest = SelectSingleNode("/manifest"); if (!manifest.InnerXml.Contains("android.permission.CAMERA")) { XmlElement child = CreateElement("uses-permission"); manifest.AppendChild(child); XmlAttribute newAttribute = CreateAndroidAttribute("name", "android.permission.CAMERA"); child.Attributes.Append(newAttribute); } //else //{ // NRDebugger.Info("Already has the camera permission."); //} } internal void SetPackageReadPermission() { var manifest = SelectSingleNode("/manifest"); if (!manifest.InnerXml.Contains("android.permission.QUERY_ALL_PACKAGES")) { XmlElement child = CreateElement("uses-permission"); manifest.AppendChild(child); XmlAttribute newAttribute = CreateAndroidAttribute("name", "android.permission.QUERY_ALL_PACKAGES"); child.Attributes.Append(newAttribute); } //else //{ // NRDebugger.Info("Already has the permission of 'android.permission.QUERY_ALL_PACKAGES'."); //} } /// Sets blue tooth permission. internal void SetBlueToothPermission() { var manifest = SelectSingleNode("/manifest"); if (!manifest.InnerXml.Contains("android.permission.BLUETOOTH")) { XmlElement child = CreateElement("uses-permission"); manifest.AppendChild(child); XmlAttribute newAttribute = CreateAndroidAttribute("name", "android.permission.BLUETOOTH"); child.Attributes.Append(newAttribute); // newAttribute = CreateAndroidAttribute("name", "android.permission.BLUETOOTH_ADMIN"); // child.Attributes.Append(newAttribute); } //else //{ // NRDebugger.Info("Already has the bluetooth permission."); //} } internal void SetAudioRecordPermission() { var manifest = SelectSingleNode("/manifest"); if (!manifest.InnerXml.Contains("android.permission.RECORD_AUDIO")) { XmlElement child = CreateElement("uses-permission"); manifest.AppendChild(child); XmlAttribute newAttribute = CreateAndroidAttribute("name", "android.permission.RECORD_AUDIO"); child.Attributes.Append(newAttribute); } } /// Sets sdk meta data. internal void SetSDKMetaData() { var activity = SelectSingleNode("/manifest/application"); // metadata for "nreal_sdk var newMetaNRSDK = SelectSingleNode("/manifest/application/meta-data[@android:name='nreal_sdk' and " + "@android:value='true']", nameSpaceManager); var oldMetaNRSDK = SelectSingleNode("/manifest/application/meta-data[@android:name='nreal_sdk']", nameSpaceManager); if (newMetaNRSDK == null) { if (oldMetaNRSDK != null) { activity.RemoveChild(oldMetaNRSDK); } XmlElement child = CreateElement("meta-data"); activity.AppendChild(child); XmlAttribute newAttribute = CreateAndroidAttribute("name", "nreal_sdk"); child.Attributes.Append(newAttribute); newAttribute = CreateAndroidAttribute("value", "true"); child.Attributes.Append(newAttribute); } // metadata for "com.nreal.supportDevices" string supportDevices = NRProjectConfigHelper.GetProjectConfig().GetTargetDeviceTypesDesc(); var newMetaDevices = SelectSingleNode("/manifest/application/meta-data[@android:name='com.nreal.supportDevices' and " + "@android:value='']", nameSpaceManager); var oldMetaDevices = SelectSingleNode("/manifest/application/meta-data[@android:name='com.nreal.supportDevices']", nameSpaceManager); if (oldMetaDevices != null) activity.RemoveChild(oldMetaDevices); if (newMetaDevices == null) { XmlElement child = CreateElement("meta-data"); activity.AppendChild(child); XmlAttribute newAttribute = CreateAndroidAttribute("name", "com.nreal.supportDevices"); child.Attributes.Append(newAttribute); newAttribute = CreateAndroidAttribute("value", supportDevices); child.Attributes.Append(newAttribute); } } /// Sets a pk displayed on launcher. /// True to show, false to hide. internal void SetAPKDisplayedOnLauncher(bool show) { var activity = GetActivityWithLaunchIntent(); if (activity == null) { activity = GetActivityWithInfoIntent(); } var intentfilter = SelectSingleNode("/manifest/application/activity/intent-filter[action/@android:name='android.intent.action.MAIN']", nameSpaceManager); var categoryInfo = SelectSingleNode("/manifest/application/activity/intent-filter/category[@android:name='android.intent.category.INFO']", nameSpaceManager); var categoryLauncher = SelectSingleNode("/manifest/application/activity/intent-filter/category[@android:name='android.intent.category.LAUNCHER']", nameSpaceManager); if (show) { // Add launcher category XmlElement newcategory = CreateElement("category"); XmlAttribute newAttribute = CreateAndroidAttribute("name", "android.intent.category.LAUNCHER"); newcategory.Attributes.Append(newAttribute); if (categoryInfo != null) { intentfilter.ReplaceChild(newcategory, categoryInfo); } else if (categoryLauncher == null) { intentfilter.AppendChild(newcategory); } } else { // Add info category XmlElement newcategory = CreateElement("category"); XmlAttribute newAttribute = CreateAndroidAttribute("name", "android.intent.category.INFO"); newcategory.Attributes.Append(newAttribute); newAttribute = CreateAndroidAttribute("node", "replace", "tools"); newcategory.Attributes.Append(newAttribute); if (categoryLauncher != null) { intentfilter.ReplaceChild(newcategory, categoryLauncher); } else if (categoryInfo == null) { intentfilter.AppendChild(newcategory); } } } } }