using System.Collections.Generic; namespace Guru.Editor { using System.Xml; using System.IO; using UnityEngine; /// /// Android 配置修改器 /// public class MainManifestDoc { private const string TargetPath = "Plugins/Android/AndroidManifest.xml"; private const string XmlnsAndroid = "xmlns:android"; private const string NamespaceAndroid = "http://schemas.android.com/apk/res/android"; private const string XmlnsTools= "xmlns:tools"; private const string NamespaceTools = "http://schemas.android.com/tools"; private XmlDocument _doc; public XmlDocument Doc => _doc; private string _docPath; private bool _isReady = false; private XmlElement _manifestNode; private XmlElement _applicationNode; private XmlNodeList _metadataList; private XmlNodeList _permissionList; #region Initiallize /// /// 加载文件 /// /// /// public static MainManifestDoc Load(string docPath = "") { if (string.IsNullOrEmpty(docPath)) { docPath = Path.GetFullPath(Path.Combine(Application.dataPath, TargetPath)); } if (!File.Exists(docPath)) { Debug.LogError($"--- File not found: {docPath}"); return null; } var mod = new MainManifestDoc(); mod.ReadFromPath(docPath); return mod; } public static MainManifestDoc Read(string xmlStr, string docPath = "") { var mod = new MainManifestDoc(); mod.ReadFromXml(xmlStr, docPath); return mod; } /// /// 从文件路径读取 /// /// public void ReadFromPath(string docPath) { _isReady = false; if (File.Exists(_docPath)) { _docPath = docPath; var xmlStr = File.ReadAllText(docPath); ReadFromXml(xmlStr); } } public void ReadFromXml(string xmlStr, string docPath = "") { _doc = new XmlDocument(); _doc.LoadXml(xmlStr); Init(); } /// /// Initializes the Doc /// private void Init() { // --- Root Nodes --- _manifestNode = _doc.SelectSingleNode("manifest") as XmlElement; _applicationNode = _doc.SelectSingleNode("manifest/application") as XmlElement; // --- Metadatas --- _metadataList = _applicationNode.SelectNodes("meta-data"); // --- Permissions --- _permissionList = _applicationNode.SelectNodes("uses-permission"); AddXmlnsAndroid(); AddXmlnsTools(); _isReady = true; } /// /// Save Doc /// public void Save(string docPath = "") { if (_isReady) { if(string.IsNullOrEmpty(docPath)) docPath = _docPath; if (!string.IsNullOrEmpty(docPath)) { var dir = Directory.GetParent(docPath); if(!dir.Exists) dir.Create(); _doc.Save(_docPath); } } } #endregion #region Node Opreation public static bool AddAttribute(XmlElement node, string key, string value) { if (node != null) { if (node.HasAttribute(key)) { node.Attributes[key].Value = value; } else { node.SetAttribute(key, value); } return true; } return false; } #endregion #region API public bool AddXmlnsAndroid() { return AddAttribute(_manifestNode, XmlnsAndroid, NamespaceAndroid); } public bool AddXmlnsTools() { return AddAttribute(_manifestNode, XmlnsTools, NamespaceTools); } /// /// Add Replace Item /// /// public void AddReplaceItem(string item) { if (_manifestNode != null) { List items = new List(5); if (_manifestNode.HasAttribute("replace", NamespaceTools)) { var arr = _manifestNode.GetAttribute("replace",NamespaceTools).Split(','); if(arr != null && arr.Length > 0) { items.AddRange(arr); } } if (!items.Contains(item)) items.Add(item); _manifestNode.SetAttribute("replace", NamespaceTools, string.Join(",", items)); } } /// /// Set metadata /// /// /// public void SetMetadata(string key, string value) { _metadataList = _applicationNode?.SelectNodes("meta-data") ?? null; XmlElement item = null; if (_metadataList != null) { foreach (XmlElement e in _metadataList) { // var nm = e.GetAttribute("name", NamespaceAndroid); if (e.GetAttribute("name", NamespaceAndroid) is string k && k == key) { item = e; break; } } } if (item == null) { item = _doc.CreateElement("meta-data"); _applicationNode?.AppendChild(item); } item.SetAttribute("name", NamespaceAndroid, key); item.SetAttribute("value", NamespaceAndroid, value); } #endregion #region Output public override string ToString() { if (_doc != null) return _doc.InnerXml; return this.ToString(); } #endregion } }