#if UNITY_ANDROID using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml.Linq; using UnityEngine; using UnityEditor; using UnityEditor.Android; namespace Topon_Adapter.Editor { public class AD_BuildAndroidProcess : IPostGenerateGradleAndroidProject { private static readonly XNamespace AndroidNamespace = "http://schemas.android.com/apk/res/android"; private static readonly XNamespace ToolsNamespace = "http://schemas.android.com/tools"; public void OnPostGenerateGradleAndroidProject (string path) { ProcessAndroidManifest (path); } public static void ProcessAndroidManifest (string path) { #if UNITY_2019_3_OR_NEWER var manifestPath = Path.Combine (path, "src/main/AndroidManifest.xml"); var launcherManifestPath = Path.Combine (path, "../launcher/src/main/AndroidManifest.xml"); #else var manifestPath = Path.Combine(path, "unityLibrary/src/main/AndroidManifest.xml"); #endif // var manifestPath = Path.Combine(path, "src/main/AndroidManifest.xml"); XDocument manifest; XDocument launcherManifest; try { manifest = XDocument.Load (manifestPath); launcherManifest = XDocument.Load (launcherManifestPath); } #pragma warning disable 0168 catch (IOException exception) #pragma warning restore 0168 { ATLog.log ("[BuildAndroidProcess] AndroidManifest.xml is missing."); return; } #if UNITY_2019_3_OR_NEWER var resXmlPath = Path.Combine(path, "src/main/res/xml"); #else var resXmlPath = Path.Combine(path, "unityLibrary/src/main/res/xml"); #endif if (!Directory.Exists(resXmlPath)) { Directory.CreateDirectory(resXmlPath); } // var fromScriptableObject = MonoScript.FromScriptableObject(this); var xmlPath = GetScriptsPath("AD_BuildAndroidProcess"); saveFile($"{xmlPath}/alex_tt_file_path.xml", resXmlPath); // Get the `manifest` element. var elementManifest = manifest.Element ("manifest"); if (elementManifest == null) { ATLog.log ("[BuildAndroidProcess] AndroidManifest.xml is invalid."); return; } var elementApplication = elementManifest.Element ("application"); if (elementApplication == null) { ATLog.log ("[BuildAndroidProcess] AndroidManifest.xml is invalid."); return; } ToSingleTop (elementManifest); var queries = CreateQueries (); var xManifestElements = elementManifest.Descendants (); var xApplicationElements = elementApplication.Descendants (); var useQueries = xManifestElements.Where (element => element.Name.LocalName.Equals ("package")); XElement tencentElement = GetElementByName (useQueries, "com.tencent.mm"); if (tencentElement == null) { elementManifest.Add (queries); } var wxElements = xApplicationElements.Where (element => element.Name.LocalName.Equals ("activity")); XElement wxElement = GetElementByName (wxElements, ".wxapi.WXEntryActivity"); if (wxElement != null) { wxElement.Remove (); } elementApplication.Add (CreateActivityXML ()); var elementlauncherManifest = launcherManifest.Element ("manifest"); var elementlauncherApplication = elementlauncherManifest.Element ("application"); var launcherElements = elementlauncherApplication.Descendants ().Where (element => element.Name.LocalName.Equals ("provider")); XElement launcherElement = GetElementByName (launcherElements, "com.bytedance.sdk.openadsdk.TTFileProvider"); if (launcherElement == null) { //增加穿山甲配置 elementlauncherApplication.Add (CreateCSJGromore ()); } var elementMainManifest = manifest.Element ("manifest"); var elementMainApplication = elementMainManifest.Element ("application"); var mainElements = elementMainApplication.Descendants ().Where (element => element.Name.LocalName.Equals ("provider")); XElement mainElement = GetElementByName (mainElements, "com.bytedance.sdk.openadsdk.TTFileProvider"); if (mainElement == null) { //增加穿山甲配置 elementMainApplication.Add (CreateCSJGromore ()); } // Save the updated manifest file. manifest.Save (manifestPath); launcherManifest.Save (launcherManifestPath); } public static void saveFile(string filePathName , string toFilesPath) { FileInfo file = new FileInfo(filePathName); string newFileName = file.Name; file.CopyTo(toFilesPath + "/" + newFileName, true); } /// /// 增加微信开放平台的适配 /// public static XElement CreateActivityXML () { var metaData = new XElement ("activity"); metaData.Add (new XAttribute (AndroidNamespace + "name", ".wxapi.WXEntryActivity")); metaData.Add (new XAttribute (AndroidNamespace + "label", "@string/app_name")); metaData.Add (new XAttribute (AndroidNamespace + "theme", "@android:style/Theme.Translucent.NoTitleBar")); metaData.Add (new XAttribute (AndroidNamespace + "exported", "true")); metaData.Add (new XAttribute (AndroidNamespace + "taskAffinity", Application.identifier)); metaData.Add (new XAttribute (AndroidNamespace + "launchMode", "singleTop")); return metaData; } public static XElement CreateQueries () { var metaData = new XElement ("queries"); var packageData = new XElement ("package"); packageData.Add (new XAttribute (AndroidNamespace + "name", "com.tencent.mm")); metaData.Add (packageData); return metaData; } private static XElement GetElementByName (IEnumerable elements, string name) { foreach (var element in elements) { var attributes = element.Attributes (); if (attributes.Any (attribute => attribute.Name.Namespace.Equals (AndroidNamespace) && attribute.Name.LocalName.Equals ("name") && attribute.Value.Equals (name))) { return element; } } return null; } public static string GetScriptsPath (string scriptName) { string[] path = UnityEditor.AssetDatabase.FindAssets(scriptName); if(path.Length >1) { // Debug.LogError("有同名文件"+_scriptName+"获取路径失败"); return null; } //将字符串中得脚本名字和后缀统统去除掉 string _path = AssetDatabase.GUIDToAssetPath(path[0]).Replace((@"/" +scriptName +".cs"),""); return _path; } public static XElement CreateCSJGromore () { // ReSharper disable once InvalidXmlDocComment /** * * */ var providerData = new XElement ("provider"); providerData.Add (new XAttribute (AndroidNamespace + "name" , "com.bytedance.sdk.openadsdk.TTFileProvider")); providerData.Add (new XAttribute (AndroidNamespace + "authorities" , "${applicationId}.TTFileProvider")); providerData.Add (new XAttribute (AndroidNamespace + "exported" , "false")); providerData.Add (new XAttribute (AndroidNamespace + "grantUriPermissions" , "true")); providerData.Add (new XAttribute (ToolsNamespace + "replace" , "android:authorities")); var metaData = new XElement ("meta-data"); metaData.Add (new XAttribute (AndroidNamespace + "name" , "android.support.FILE_PROVIDER_PATHS")); // metaData.Add (new XAttribute (AndroidNamespace + "resource" , "@xml/alex_tt_file_path")); metaData.Add (new XAttribute (AndroidNamespace + "resource" , "@xml/anythink_bk_tt_file_path")); providerData.Add (metaData); return providerData; } public static void ToSingleTop (XElement manifest) { var elements = manifest.Descendants ().Where (element => element.Name.LocalName.Equals ("activity")); // 如果这个activity已经有了 android:launchMode="singleTask",则不再添加 XElement elementByName = GetElementByName (elements , "com.unity3d.player.UnityPlayerActivity"); //此处将 android:launchMode="singleTask" 改为 android:launchMode="singleTop" // elementByName.Add (new XAttribute (AndroidNamespace + "launchMode", "singleTop")); elementByName.Attribute ( AndroidNamespace + "launchMode")?.SetValue ("singleTop"); } public int callbackOrder { get; } } } #endif