389 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			389 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
 | 
						||
 | 
						||
 | 
						||
namespace Guru.Editor
 | 
						||
{
 | 
						||
    using System.Xml;
 | 
						||
    using System.IO;
 | 
						||
    using UnityEngine;
 | 
						||
    using System.Collections.Generic;
 | 
						||
    
 | 
						||
    
 | 
						||
    /// <summary>
 | 
						||
    /// Android 配置修改器
 | 
						||
    /// </summary>
 | 
						||
    public class AndroidManifestDoc
 | 
						||
    {
 | 
						||
        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 const string UserPermission = "uses-permission";
 | 
						||
        private const string MetaData = "meta-data";
 | 
						||
        private const string KName = "name";
 | 
						||
 | 
						||
        private XmlDocument _doc;
 | 
						||
        public XmlDocument Doc => _doc;
 | 
						||
 | 
						||
        private string _docPath;
 | 
						||
        private bool _isReady = false;
 | 
						||
        
 | 
						||
        private XmlElement _manifestNode;
 | 
						||
        private XmlElement _applicationNode;
 | 
						||
        private XmlElement _queriesNode;
 | 
						||
 | 
						||
        
 | 
						||
        #region Initiallize
 | 
						||
        
 | 
						||
        /// <summary>
 | 
						||
        /// 加载文件
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="docPath"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public static AndroidManifestDoc 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 AndroidManifestDoc();
 | 
						||
            mod.ReadFromPath(docPath);
 | 
						||
            return mod;
 | 
						||
        }
 | 
						||
 | 
						||
        public static AndroidManifestDoc Read(string xmlStr, string docPath = "")
 | 
						||
        {
 | 
						||
            var mod = new AndroidManifestDoc();
 | 
						||
            mod.ReadFromXml(xmlStr, docPath);
 | 
						||
            return mod;
 | 
						||
        }
 | 
						||
        
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 从文件路径读取
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="docPath"></param>
 | 
						||
        public void ReadFromPath(string docPath)
 | 
						||
        {
 | 
						||
            _isReady = false;
 | 
						||
            if (File.Exists(docPath))
 | 
						||
            {
 | 
						||
                var xmlStr = File.ReadAllText(docPath);
 | 
						||
                ReadFromXml(xmlStr, docPath);
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                Debug.LogError($"--- File not found: {docPath}");
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        public void ReadFromXml(string xmlStr, string docPath = "")
 | 
						||
        {
 | 
						||
            _doc = new XmlDocument();
 | 
						||
            _doc.LoadXml(xmlStr);
 | 
						||
            if(!string.IsNullOrEmpty(docPath)) _docPath = docPath;
 | 
						||
            Init();
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// Initializes the Doc
 | 
						||
        /// </summary>
 | 
						||
        private void Init()
 | 
						||
        {
 | 
						||
            // --- Root Nodes ---
 | 
						||
            _manifestNode = _doc.SelectSingleNode("manifest") as XmlElement;
 | 
						||
            _applicationNode = _doc.SelectSingleNode("manifest/application") as XmlElement;
 | 
						||
            _queriesNode = _doc.SelectSingleNode("manifest/queries") as XmlElement;
 | 
						||
            
 | 
						||
            
 | 
						||
            AddXmlnsAndroid();
 | 
						||
            AddXmlnsTools();
 | 
						||
            _isReady = true;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// Save Doc
 | 
						||
        /// </summary>
 | 
						||
        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);
 | 
						||
        }
 | 
						||
        
 | 
						||
        /// <summary>
 | 
						||
        /// Add Replace Item
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="item"></param>
 | 
						||
        public void AddApplicationReplaceItem(string item)
 | 
						||
        {
 | 
						||
            if (_applicationNode != null)
 | 
						||
            {
 | 
						||
                List<string> items = new List<string>(5);
 | 
						||
                if (_applicationNode.HasAttribute("replace", NamespaceTools))
 | 
						||
                {
 | 
						||
                    var arr = _applicationNode.GetAttribute("replace",NamespaceTools).Split(',');
 | 
						||
                    if(arr != null && arr.Length > 0)
 | 
						||
                    {
 | 
						||
                        items.AddRange(arr);
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
                if (!items.Contains(item)) items.Add(item);
 | 
						||
                
 | 
						||
                _applicationNode.SetAttribute("replace",  NamespaceTools, string.Join(",", items));
 | 
						||
            }
 | 
						||
        }
 | 
						||
        
 | 
						||
        public void SetApplicationAttribute(string key, string value)
 | 
						||
        {
 | 
						||
            if (_applicationNode != null)
 | 
						||
            {
 | 
						||
                _applicationNode.SetAttribute(key, NamespaceAndroid, value);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        
 | 
						||
        /// <summary>
 | 
						||
        /// Set metadata
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="key"></param>
 | 
						||
        /// <param name="value"></param>
 | 
						||
        /// <param name="valueName"></param>
 | 
						||
        /// <param name="keyName"></param>
 | 
						||
        public void SetMetadata(string key, string value, string valueName = "value", string keyName = KName)
 | 
						||
        {
 | 
						||
            if (_doc == null || !_isReady) return;
 | 
						||
            
 | 
						||
            XmlElement node = null;
 | 
						||
            if (!TryGetMetadata(key, out node, keyName))
 | 
						||
            {
 | 
						||
                node = _doc.CreateElement(MetaData);
 | 
						||
                _applicationNode?.AppendChild(node);
 | 
						||
            }
 | 
						||
 | 
						||
            node.SetAttribute(keyName, NamespaceAndroid, key);
 | 
						||
            node.SetAttribute(valueName, NamespaceAndroid, value);
 | 
						||
        }
 | 
						||
 | 
						||
        
 | 
						||
        /// <summary>
 | 
						||
        /// 添加权限
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="key"></param>
 | 
						||
        /// <param name="keyName"></param>
 | 
						||
        public void AddPermission(string key, string keyName = KName)
 | 
						||
        {
 | 
						||
            if (_doc == null || !_isReady) return;
 | 
						||
 | 
						||
            XmlElement node = null;
 | 
						||
            if(!TryGetPermission(key, out node, keyName))
 | 
						||
            {
 | 
						||
                node = _doc.CreateElement(UserPermission);
 | 
						||
                _manifestNode?.AppendChild(node);
 | 
						||
            }
 | 
						||
            node.SetAttribute(keyName, NamespaceAndroid, key);
 | 
						||
        }
 | 
						||
        
 | 
						||
        /// <summary>
 | 
						||
        /// 删除 Permission
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="key"></param>
 | 
						||
        /// <param name="value"></param>
 | 
						||
        /// <param name="keyName"></param>
 | 
						||
        /// <param name="valueName"></param>
 | 
						||
        public void RemovePermission(string key, string value = "remove", string keyName = "name",  string valueName = "node")
 | 
						||
        {
 | 
						||
            if (_doc == null || !_isReady) return;
 | 
						||
            
 | 
						||
            XmlElement node = null;
 | 
						||
            if(!TryGetPermission(key, out node, keyName))
 | 
						||
            {
 | 
						||
                node = _doc.CreateElement(UserPermission);
 | 
						||
                _manifestNode?.AppendChild(node);
 | 
						||
            }
 | 
						||
            node.SetAttribute(keyName, NamespaceAndroid, key);
 | 
						||
            node.SetAttribute(valueName, NamespaceTools, value);
 | 
						||
        }
 | 
						||
        
 | 
						||
        public bool SetPackageName(string packageName)
 | 
						||
        {
 | 
						||
            if (_manifestNode != null)
 | 
						||
            {
 | 
						||
                _manifestNode.Attributes["package"].Value = packageName;
 | 
						||
                return true;
 | 
						||
            }
 | 
						||
            return false;
 | 
						||
        }
 | 
						||
        
 | 
						||
        /// <summary>
 | 
						||
        /// 添加 Queries Intent
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="value"></param>
 | 
						||
        /// <param name="keyName"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public void AddQueriesIntent(string value, string keyName = "name")
 | 
						||
        {
 | 
						||
            if (_queriesNode == null)
 | 
						||
            {
 | 
						||
                _queriesNode = _doc.CreateElement("queries");
 | 
						||
                _manifestNode?.AppendChild(_queriesNode);
 | 
						||
            }
 | 
						||
 | 
						||
            var intentList = _queriesNode.SelectNodes("intent");
 | 
						||
            if (intentList != null)
 | 
						||
            {
 | 
						||
                foreach (XmlElement intent in intentList)
 | 
						||
                {
 | 
						||
                    var action = intent?.SelectSingleNode("action") as XmlElement;
 | 
						||
                    
 | 
						||
                    if (action != null 
 | 
						||
                        && action.GetAttribute(keyName, NamespaceAndroid) == value)
 | 
						||
                    {
 | 
						||
                        return; // Has injected,skip ...
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
            
 | 
						||
            // Inject new intent node
 | 
						||
            XmlElement intentNode = _doc.CreateElement("intent");
 | 
						||
            _queriesNode.AppendChild(intentNode);
 | 
						||
            XmlElement actionNode = _doc.CreateElement("action");
 | 
						||
            intentNode.AppendChild(actionNode);
 | 
						||
            actionNode.SetAttribute(keyName, NamespaceAndroid, value);
 | 
						||
        }
 | 
						||
        
 | 
						||
        
 | 
						||
        #endregion
 | 
						||
 | 
						||
        #region Data Opration
 | 
						||
 | 
						||
        public bool TryGetMetadata(string name, out XmlElement node, string keyName = KName)
 | 
						||
        {
 | 
						||
            node = null;
 | 
						||
 | 
						||
            if(_applicationNode != null)
 | 
						||
            {
 | 
						||
                var list = _applicationNode.SelectNodes(MetaData);
 | 
						||
                if (list != null)
 | 
						||
                {
 | 
						||
                    foreach (XmlElement e in list)
 | 
						||
                    {
 | 
						||
                        if (e.GetAttribute(keyName, NamespaceAndroid) == name)
 | 
						||
                        {
 | 
						||
                            node = e;
 | 
						||
                            return true;
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
            return false;
 | 
						||
        }
 | 
						||
        
 | 
						||
        
 | 
						||
        public bool TryGetPermission(string name, out XmlElement node, string keyName = KName)
 | 
						||
        {
 | 
						||
            node = null;
 | 
						||
 | 
						||
            if(_manifestNode != null)
 | 
						||
            {
 | 
						||
                var list = _manifestNode.SelectNodes(UserPermission);
 | 
						||
                if (list != null)
 | 
						||
                {
 | 
						||
                    foreach (XmlElement e in list)
 | 
						||
                    {
 | 
						||
                        if (e.GetAttribute(keyName, NamespaceAndroid) == name)
 | 
						||
                        {
 | 
						||
                            node = e;
 | 
						||
                            return true;
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
            return false;
 | 
						||
        }
 | 
						||
        
 | 
						||
        public bool TryRootNode(string nodeName, out XmlElement node)
 | 
						||
        {
 | 
						||
            node = null;
 | 
						||
            if (_doc != null)
 | 
						||
            {
 | 
						||
                node = _doc.SelectSingleNode(nodeName) as XmlElement;
 | 
						||
                return node != null;
 | 
						||
            }
 | 
						||
            return false;
 | 
						||
        }
 | 
						||
        
 | 
						||
        #endregion
 | 
						||
        
 | 
						||
        #region Output
 | 
						||
 | 
						||
 | 
						||
        public override string ToString()
 | 
						||
        {
 | 
						||
            if (_doc != null) return _doc.InnerXml;
 | 
						||
            return this.ToString();
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        #endregion
 | 
						||
        
 | 
						||
    }
 | 
						||
} |