为了实现不同Android渠道,采用不同的 AndroidManifest 配置。
需要在Unity打包前,通过代码自动修改 AndroidManifest.xml 文件的内容,实现自动化一键生成,减少了生成 android studio 工程后再修改的麻烦。
首先,Unity 提供了打包前和打包后调用的接口(interface)
IPreprocessBuildWithReport.OnPreprocessBuild
IPostprocessBuildWithReport.OnPostprocessBuild
其次,C# 提供了修改 XML 文件的库 System.Xml
方便了我们对 AndroidManifest.xml 文件进行增删改查
最后,为了实现灵活配置,采用了 Json 文件作为配置文件
独立的 Json 文件便于管理,保存在工程特定目录。
我这里使用的为 Newtonsoft.Json 库,小巧
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using System.IO;
using System.Xml;
using Newtonsoft.Json;/// <summary>
/// created by lymancao @ 2023.08.23
/// 说明:
/// 为了针对不同Android渠道,进行 AndroidManifest 文件的不同配置,特意实现此功能。
/// 利用 Unity 提供的打包前调用接口,C#的XML库
/// 引入 Newtonsoft.Json 库 处理Json格式的配置文件
/// 实现了打包前自动根据渠道修改android清单文件的功能。
/// </summary>
public class CustomBuildProcesser : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{// 调用顺序,数值越小,调用越早public int callbackOrder{get { return 0; }}public const string AndroidManifest_Config_Google = "Assets/Config/Android/google.json";public const string AndroidManifest_Config_Amazon = "Assets/Config/Android/amazon.json";// build 开始时public void OnPreprocessBuild(BuildReport report){//throw new System.NotImplementedException();if (report.summary.platform == BuildTarget.Android){// 读取配置,一定要保证配置的正确性string configPath;if (PackageTool.targetPlatform == TargetPlatform.GooglePlay)configPath = AndroidManifest_Config_Google;else if (PackageTool.targetPlatform == TargetPlatform.Amazon)configPath = AndroidManifest_Config_Amazon;elsereturn;OnPreprocessBuildForAndroid(report, configPath);}}// build 完成时public void OnPostprocessBuild(BuildReport report){if (report.summary.platform == BuildTarget.Android){OnPostprocessBuildForAndroid(report);}}/// <summary>/// 在生成android apk前,将一些配置写入AndroidManifest.xml/// </summary>/// <param name="report"></param>public static void OnPreprocessBuildForAndroid(BuildReport report, string configPath){Debug.Log("========== ========== OnPreprocessBuildForAndroid Start ========== ==========");// 判断 Json 配置文件是否存在if (!File.Exists(configPath)){Debug.LogError("OnPostprocessBuildForAndroid Error: " + configPath + " doesn't exist.");return;}string jsonContent = File.ReadAllText(configPath);// 将 json 解析为一个字典Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonContent);// 将 json 映射到一个类 //AndroidManifestConfig config = JsonConvert.DeserializeObject<AndroidManifestConfig>(configContent);ModifyAndroidManifest();AssetDatabase.Refresh();Debug.Log("========== ========== OnPreprocessBuildForAndroid Done ========== ==========");}public static void ModifyAndroidManifest(){// 读取xmlstring xmlPath = Application.dataPath + "/Plugins/Android/AndroidManifest.xml";XmlDocument xmlDoc = new XmlDocument();xmlDoc.Load(xmlPath);// 包名XmlNode rootNode = xmlDoc.SelectSingleNode("/manifest");Debug.Log("package name = " + rootNode.Attributes["package"].Value);// 修改//rootNode.Attributes["package"].Value = jsonDict["app_package_name"].ToString();// 遍历所有权限XmlNodeList nodeList = rootNode.SelectNodes("/manifest/uses-permission");for (int i = 0; i < nodeList.Count; i++){Debug.Log(" <" + nodeList[i].Name + " " + nodeList[i].LocalName + " " + nodeList[i].Attributes["android:name"].Value + ">");// 删除特定权限if (nodeList[i].Attributes["android:name"].Value == "android.permission.TEST"){Debug.Log("Remove Node " + nodeList[i].Name + " " + nodeList[i].Attributes["android:name"].Value);rootNode.RemoveChild(nodeList[i]);}}// 添加XmlNode newNode = xmlDoc.CreateElement("uses-permission");string ns = rootNode.GetNamespaceOfPrefix("android");XmlAttribute newAttr = newNode.Attributes.Append(xmlDoc.CreateAttribute("name", ns));newAttr.Value = "android.permission.TEST";Debug.Log("Append Node " + newNode.Name + " " + newAttr.Name + " in "+ns);rootNode.AppendChild(newNode);// 获取指定位置节点XmlNode node = FindNode(xmlDoc, "/manifest/application/activity/intent-filter/data", "android:scheme", "com.funtriolimited.slots.casino.free");if (node != null){Debug.Log("android:scheme = "+ node.Attributes["android:scheme"].Value);// 修改//node.Attributes["android:scheme"].Value = jsonDict["url_schemes_name"].ToString();}// 保存xmlDoc.Save(xmlPath);}/// <summary>/// 在生成android apk后,将一些配置写入AndroidManifest.xml/// </summary>/// <param name="report"></param>static void OnPostprocessBuildForAndroid(BuildReport report){Debug.Log("OnPostprocessBuildForAndroid Start");// TODODebug.Log("OnPostprocessBuildForAndroid Done");}static XmlNode FindNode(XmlDocument xmlDoc, string xpath, string attributeName, string attributeValue){XmlNodeList nodes = xmlDoc.SelectNodes(xpath);for (int i = 0; i < nodes.Count; i++){XmlNode node = nodes.Item(i);string _attributeValue = node.Attributes[attributeName].Value;if (_attributeValue == attributeValue){return node;}}return null;}}
Unity 打包前,通过代码对 AndroidManifest 增删改查_androidmanifest 修改-CSDN博客