4

I made a 2D game that uses post-processing effects. As a result, the game runs fine on my old crappy tablet when post-processing is off and stutters when it's on, but I'd like to explore my possibilities.

Is there a way to force android hardware acceleration in my Unity projects?

Edit: I put this manifest inside my project's android folder.

Did I do it right? No significant difference in performance.

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.unity3d.player"
    xmlns:tools="http://schemas.android.com/tools"
    android:installLocation="preferExternal"
    android:versionCode="1"
    android:versionName="1.0">
    <supports-screens
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true"
        android:anyDensity="true"/>

    <application
        android:hardwareAccelerated="true"
        android:theme="@style/UnityThemeSelector"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name">
        <activity android:name="com.unity3d.player.UnityPlayerActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
    </application>
</manifest>

The editor screenshot:

enter image description here

agiro
  • 2,018
  • 2
  • 30
  • 62

2 Answers2

5

Programmer's answer only works if you don't have any other android plugins with their own Android Manifests. This is the foolproof way to do it (Unity 2018.1+):

  1. Download the Assets/Editor/ModifyUnityAndroidAppManifestSample.cs script here and place it in the same location in your project.

  2. Add the following function to the AndroidManifest class:

    internal void SetHardwareAccel(){
       GetActivityWithLaunchIntent().Attributes.Append(CreateAndroidAttribute("hardwareAccelerated", "true")); 
    }  
    
  3. Call androidManifest.SetHardwareAccel(); in OnPostGenerateGradleAndroidProject(string basePath)

EDIT: In case the above link breaks or you hate following multiple steps (don't we all), here is the class (includes the above method and call) you can paste into 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.SetHardwareAccel();

        // 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 SetHardwareAccel(){
        GetActivityWithLaunchIntent().Attributes.Append(CreateAndroidAttribute("hardwareAccelerated", "true"));
}
}
Jacksonkr
  • 31,583
  • 39
  • 180
  • 284
pale bone
  • 1,746
  • 2
  • 19
  • 26
3

Just add android:hardwareAccelerated="true"> to the Android Manifest inside the <application tag. That's it.

Here are the steps:

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

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

Add android:hardwareAccelerated="true"> to it after <application. Save, Build and Run.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Thanks. By the way, I head that the reason this isn't default is because this hardware accel is a bit buggy (or at least was) and is not that stable. Is there a failsafe way to switch this on or off? Maybe even from inside the app? – agiro Aug 22 '17 at 14:51
  • 1
    I used to use this on Google Glasses few years ago. No problem at-all. Maybe there are problems on some devices. See [this](https://stackoverflow.com/a/16469015/3785314) answer for how to do it via code. It gives advice to disable it by default in the Manifest. – Programmer Aug 22 '17 at 14:56
  • You are welcome. I believe the Java code in that answer **may** also be converted into C# with `AndroidJavaClass`. I am too lazy to do that but if you are interested and give it a try and fail, I might give it a try when I have time if you create a new question for it. – Programmer Aug 22 '17 at 15:01
  • I give a shot to using just the xml stuff. I test it on like 3 devices (all low end) and if good, no prob. Maybe if I get a lot of down vote, I clear that out :D – agiro Aug 22 '17 at 15:02
  • 1
    Ok good. Always good to test. Make sure all devices are from different manufactures. Happy coding! – Programmer Aug 22 '17 at 15:04
  • Uhh I did the thing but no noticable performance improvement (and still stable). I have the given manifest `xml` in my Android folder inside my plugins in my project. Did I do what I had to? – agiro Aug 22 '17 at 15:16
  • The xml file looks fine. Can you put screenshot of the directory you put it in the Editor? I want to see. – Programmer Aug 22 '17 at 15:18
  • 1
    It looks fine. I suspect that Unity changed and is probably setting WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED from code. I suggest you go the code way. First use Java to do it. If it works then you can try to make it a C# code without Java at-all. – Programmer Aug 22 '17 at 15:27
  • So basically like the answer you linked? – agiro Aug 22 '17 at 15:28
  • The above answer did not work for me, it doesn't handle the manifest correctly if you have other android plugins – pale bone Jan 14 '19 at 22:16
  • Mr. @Programmer :) Here's a challenge for a brainy young person: https://stackoverflow.com/q/54189957/294884 – Fattie Jan 14 '19 at 22:16