Files
CC-Framework.CrashReport/Assets/Editor/CrashPostProcessBuildAndroid.cs
2024-04-03 15:13:12 +08:00

219 lines
8.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#if UNITY_ANDROID && UNITY_2018_2_OR_NEWER
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using UnityEditor;
using UnityEditor.Android;
namespace Editor
{
public class CrashPostProcessBuildAndroid : IPostGenerateGradleAndroidProject
{
private static readonly XNamespace AndroidNamespace = "http://schemas.android.com/apk/res/android";
private static readonly XNamespace ToolsNamespace = "http://schemas.android.com/tools";
private static readonly string networkConfigXml = "network_security_config";
public int callbackOrder { get; }
public void OnPostGenerateGradleAndroidProject (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
{
return;
}
// Get the `manifest` element.
var elementManifest = manifest.Element ("manifest");
if (elementManifest == null)
{
return;
}
var elementApplication = elementManifest.Element ("application");
if (elementApplication == null)
{
return;
}
//增加必要权限
AddPermission ("android.permission.INTERNET" , elementManifest);
AddPermission ("android.permission.ACCESS_NETWORK_STATE" , elementManifest);
AddPermission ("android.permission.ACCESS_WIFI_STATE" , elementManifest);
AddPermission ("android.permission.READ_PHONE_STATE" , elementManifest);
AddPermission ("android.permission.READ_LOGS" , elementManifest);
manifest.Save (manifestPath);
launcherManifest.Save (launcherManifestPath);
processNetworkConfigXml (path);
}
public static void AddPermission (string permission , XElement manifest)
{
var metaData = new XElement ("uses-permission");
metaData.Add (new XAttribute (AndroidNamespace + "name", permission));
//判断是否已经添加过了
var isExist = manifest.Descendants ().Any (element =>
element.Name.LocalName.Equals ("uses-permission") && element.Attribute (AndroidNamespace + "name")!.Value.Equals (permission));
if (!isExist)
{
manifest.Add (metaData);
}
}
private static void processNetworkConfigXml (string path)
{
// bool isChina = true;
//在application标签加上android:networkSecurityConfig="@xml/network_security_config"
var hasAdd = addNetworkSecurityConfigInApplication (path);
#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
var rexXmlDir = Path.Combine (resXmlPath, $"{networkConfigXml}.xml");
if (File.Exists (rexXmlDir) || !hasAdd)
{
// FileUtil.DeleteFileOrDirectory (rexXmlDir);
return;
}
if (!Directory.Exists (resXmlPath))
{
Directory.CreateDirectory (resXmlPath);
}
// var fromScriptableObject = MonoScript.FromScriptableObject(this);
var xmlPath = GetScriptsPath (nameof(CrashPostProcessBuildAndroid));
saveFile ($"{xmlPath}/{networkConfigXml}.xml", resXmlPath);
}
public static void saveFile (string filePathName , string toFilesPath)
{
FileInfo file = new FileInfo (filePathName);
string newFileName = file.Name;
file.CopyTo (toFilesPath + "/" + newFileName, true);
}
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;
}
private static bool addNetworkSecurityConfigInApplication (string path)
{
#if UNITY_2019_3_OR_NEWER
var manifestPath = Path.Combine (path, "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;
try
{
manifest = XDocument.Load (manifestPath);
}
#pragma warning disable 0168
catch (IOException exception)
#pragma warning restore 0168
{
return false;
}
// Get the `manifest` element.
var elementManifest = manifest.Element ("manifest");
if (elementManifest == null)
{
return false;
}
var elementApplication = elementManifest.Element ("application");
if (elementApplication == null)
{
return false;
}
//这个设置主要是为了适配9.0以上的机器
//<uses-library android:name="org.apache.http.legacy" android:required="false" />
var usesLibraryElements = elementApplication.Descendants ().Where (element => element.Name.LocalName.Equals ("uses-library"));
XElement httpLegacyElement = GetElementByName (usesLibraryElements, "org.apache.http.legacy");
if (httpLegacyElement == null)
{
elementApplication.Add (createHttpLegacyElement ());
}
manifest.Save (manifestPath);
//handle anythink_network_security_config.xml
XAttribute networkConfigAttribute = elementApplication.Attribute (AndroidNamespace + "networkSecurityConfig");
if (networkConfigAttribute == null)
{
// networkConfigAttribute.Remove ();
elementApplication.Add (new XAttribute (AndroidNamespace + "networkSecurityConfig", $"@xml/{networkConfigXml}"));
manifest.Save (manifestPath);
return true;
}
return false;
}
public static XElement createHttpLegacyElement ()
{
var httpFeautre = new XElement ("uses-library");
httpFeautre.Add (new XAttribute (AndroidNamespace + "name", "org.apache.http.legacy"));
httpFeautre.Add (new XAttribute (AndroidNamespace + "required", "false"));
return httpFeautre;
}
private static XElement GetElementByName (IEnumerable<XElement> 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;
}
}
}
#endif