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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43293173/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 07:18:32  来源:igfitidea点击:

Use custom Manifest file and permission in Unity?

javac#androidxmlunity3d

提问by genaray

Im currently trying to program a little game for android with Unity3D. Because I want a visible status bar, I modified the AndroidManifest in the Project Folder (C:\Users\Public\Documents\Unity Projects\ProjectName\Temp\StagingArea) like this :

我目前正在尝试使用 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">

But everytime i generate the APK, unity changes the Android Manifest to this :

但是每次我生成 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 does change my modified Manifests everytime?

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

回答by Programmer

You are modifying the wrong AndroidManifestfile. That AndroidManifestfrom <ProjectName>\Temp\StagingAreayou are modifying is generated by unity each time you build your project.

您正在修改错误的AndroidManifest文件。那AndroidManifest<ProjectName>\Temp\StagingArea你正在修改通过统一每次生成项目时生成。

To use a custom AndroidManifestfile, you have to put your custom AndroidManifestfile at <ProjectName>Assets\Plugins\Android.

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

1.Go to <UnityInstallationDirecory>\Editor\Data\PlaybackEngines\AndroidPlayer\Apk, Copy the AndroidManifest.xmlfile to your <ProjectName>Assets\Plugins\Android

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

2.Open the copied Manifest file from <ProjectName>Assets\Plugins\Androidand add your manifest.

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

In your particular case, add <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">to it. Save, Build and Run.

在您的特定情况下,添加<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 will now use that AndroidManifestfile. If you get crash or any other problem, then Unity does not want you to change that.

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

回答by pale bone

Starting with Unity 2018 you should implement the IPostGenerateGradleAndroidProjectinterfacewhich will allow you to edit the android manifest after Unity produces it. In the code below I have added methods to set the microphone permission, set hardware acceleration, and set your application theme ( replace SetMicrophonePermission()to your preferred method, which is called when Unity calls OnPostGenerateGradleAndroidProject()).

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

Add the following code to Assets/Editor/ModifyUnityAndroidAppManifestSample.cs

将以下代码添加到 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);
    }
}

回答by linojon

for Unity runtime permissions, i wrote this function to add the skip permissions dialog (like https://docs.unity3d.com/Manual/android-manifest.html)

对于 Unity 运行时权限,我编写了此函数来添加跳过权限对话框(如https://docs.unity3d.com/Manual/android-manifest.html

e.g

例如

<manifest>
    <application>
        <meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />

Here's the code:

这是代码:

internal void SetSkipPermissionsDialog()
{
    var manifest = SelectSingleNode("/manifest");
    var application = manifest.SelectSingleNode("application");
    XmlElement child = CreateElement("meta-data");
    application.AppendChild(child);
    XmlAttribute newAttribute = CreateAndroidAttribute("name", "unityplayer.SkipPermissionsDialog");
    child.Attributes.Append(newAttribute);
    newAttribute = CreateAndroidAttribute("value", "true");
    child.Attributes.Append(newAttribute);
}