在 Unity 中使用自定义清单文件和权限?

2022-09-04 05:34:59

我目前正在尝试使用Unity3D为Android编写一个小游戏。因为我想要一个可见的状态栏,所以我修改了项目文件夹(C:\Users\Public\Documents\Unity Projects\ProjectName\Temp\StagingArea)中的AndroidManifest,如下所示:

<application android:theme="Theme.Light.NoTitleBar" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="true" android:banner="@drawable/app_banner">

但是每次我生成APK时,Unity都会将Android Manifest更改为:

<application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="true" android:banner="@drawable/app_banner">

Unity3D 是否每次都会更改我修改后的清单?


答案 1

您正在修改错误的文件。您正在修改的内容是在每次生成项目时由 unity 生成的。AndroidManifestAndroidManifest<ProjectName>\Temp\StagingArea

要使用自定义文件,必须将自定义文件放在 。AndroidManifestAndroidManifest<ProjectName>Assets\Plugins\Android

1.转到 ,将文件复制到您的<UnityInstallationDirecory>\Editor\Data\PlaybackEngines\AndroidPlayer\ApkAndroidManifest.xml<ProjectName>Assets\Plugins\Android

2.从中打开复制的清单文件并添加清单。<ProjectName>Assets\Plugins\Android

在您的特定情况下,请添加它。保存、构建和运行。<application android:theme="Theme.Light.NoTitleBar" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="true" android:banner="@drawable/app_banner">

Unity 现在将使用该文件。如果您遇到崩溃或任何其他问题,则Unity不希望您更改该问题。AndroidManifest


答案 2

从Unity 2018开始,您应该实现该界面,该界面将允许您在Unity生成后编辑Android清单。在下面的代码中,我添加了设置麦克风权限,设置硬件加速和设置应用程序主题的方法(替换为您的首选方法,在Unity调用时调用)。IPostGenerateGradleAndroidProjectSetMicrophonePermission()OnPostGenerateGradleAndroidProject()

将以下代码添加到Assets/Editor/ModifyUnityAndroidAppManifestSample.cs

using System.IO;
using System.Text;
using System.Xml;
using UnityEditor.Android;

public class ModifyUnityAndroidAppManifestSample : IPostGenerateGradleAndroidProject
{

    public void OnPostGenerateGradleAndroidProject(string basePath)
    {
        // If needed, add condition checks on whether you need to run the modification routine.
        // For example, specific configuration/app options enabled

        var androidManifest = new AndroidManifest(GetManifestPath(basePath));

        androidManifest.SetMicrophonePermission();

        // Add your XML manipulation routines

        androidManifest.Save();
    }

    public int callbackOrder { get { return 1; } }

    private string _manifestFilePath;

    private string GetManifestPath(string basePath)
    {
        if (string.IsNullOrEmpty(_manifestFilePath))
        {
            var pathBuilder = new StringBuilder(basePath);
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("src");
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("main");
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml");
            _manifestFilePath = pathBuilder.ToString();
        }
        return _manifestFilePath;
    }
}


internal class AndroidXmlDocument : XmlDocument
{
    private string m_Path;
    protected XmlNamespaceManager nsMgr;
    public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android";
    public AndroidXmlDocument(string path)
    {
        m_Path = path;
        using (var reader = new XmlTextReader(m_Path))
        {
            reader.Read();
            Load(reader);
        }
        nsMgr = new XmlNamespaceManager(NameTable);
        nsMgr.AddNamespace("android", AndroidXmlNamespace);
    }

    public string Save()
    {
        return SaveAs(m_Path);
    }

    public string SaveAs(string path)
    {
        using (var writer = new XmlTextWriter(path, new UTF8Encoding(false)))
        {
            writer.Formatting = Formatting.Indented;
            Save(writer);
        }
        return path;
    }
}


internal class AndroidManifest : AndroidXmlDocument
{
    private readonly XmlElement ApplicationElement;

    public AndroidManifest(string path) : base(path)
    {
        ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
    }

    private XmlAttribute CreateAndroidAttribute(string key, string value)
    {
        XmlAttribute attr = CreateAttribute("android", key, AndroidXmlNamespace);
        attr.Value = value;
        return attr;
    }

    internal XmlNode GetActivityWithLaunchIntent()
    {
        return SelectSingleNode("/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " +
                "intent-filter/category/@android:name='android.intent.category.LAUNCHER']", nsMgr);
    }

    internal void SetApplicationTheme(string appTheme)
    {
        ApplicationElement.Attributes.Append(CreateAndroidAttribute("theme", appTheme));
    }

    internal void SetStartingActivityName(string activityName)
    {
        GetActivityWithLaunchIntent().Attributes.Append(CreateAndroidAttribute("name", activityName));
    }


    internal void SetHardwareAcceleration()
    {
        GetActivityWithLaunchIntent().Attributes.Append(CreateAndroidAttribute("hardwareAccelerated", "true"));
    }

    internal void SetMicrophonePermission()
    {
        var manifest = SelectSingleNode("/manifest");
        XmlElement child = CreateElement("uses-permission");
        manifest.AppendChild(child);
        XmlAttribute newAttribute = CreateAndroidAttribute("name", "android.permission.RECORD_AUDIO");
        child.Attributes.Append(newAttribute);
    }
}

推荐