?
为了实现不同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;
else
return;
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()
{
// 读取xml
string 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");
// TODO
Debug.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博客