Unity 打包前,通过代码对 AndroidManifest 增删改查

发布时间:2024年01月03日

?

为了实现不同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博客

文章来源:https://blog.csdn.net/qq_42672770/article/details/135366306
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。