Unity的AndroidManifest中hardwareAccelerated被覆盖问题

问题分析:

​ 从事Unity Android SDK开发前后近2年,大大小小问题遇到很多,R文件的,SDK抽取出错的,反编译才能修改的,各种各样奇葩的问题。让我极为蛋疼的却不多,这个硬件加速的算得上一个。

​ 之前测试反馈,新打包的游戏播放视频广告时会黑屏,声音正常。开始不理解为什么,后面反编译后一个个对比,找到了问题,播放广告的Activity被添加了android:hardwareAccelerated=false,硬件加速被禁用。即使主动添加并设置为true打包后也会被覆盖为false。别的SDK却不会,使用该SDK的其他游戏也是正常的。由此得出结论:

1.别的SDK在代码里进行了开启硬件加速,该SDK没有。

2.部分Unity游戏的某些设置禁用了硬件加速,导致合并后为false。

因此方案就有2个:

1.反编译该SDK,开启硬件加速。

2.找出Unity的设置修改为开启。

​ 显然方案1难度不小,且在后续SDK更新后又需要重复修改,尤其在SDK混淆的情况下,极为麻烦。因此采用方案2,但是经过协同Unity同事多方查找之后仍然没有找到有用的配置,猜测是组合配置,这样想自己摸索出来,可能性几乎为零。那么就还有另外2个退而求其次的方案:

1.导出Android工程开启硬件加速后再打包。

2.向SDK平台反馈问题,等待修复。

​ 方案1最大的缺点就在于打包太麻烦,如果是偶尔打包还好,但因为公司的业务问题,每天需大量打包,显然此方案只是临时解决方案。而方案2的缺点就是等待时间不确定,毕竟有求于人嘛。很长时间以来,这个问题都是一个无法言说的痛,直到今天再次遇到这个问题,我再次进入搜索狂魔模式,终于在stackoverflow上找到了解决方案!!!

​ 但该方案仍有缺陷——只对gradle打包方式有效,老游戏就没救了,只能使用导出Android工程的方式解决。不过在Unity 2018都发了几个版本的今天,奇葩如我供职的公司,老游戏也不是那么多,因此这个缺陷可以忽略不计了。

解决方案:

1.复制ModifyUnityAndroidAppManifestSample.cs script 到你的游戏 Assets/Editor/目录下

2.在 AndroidManifest class中添加如下方法:

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

3.在 OnPostGenerateGradleAndroidProject(string basePath) 回调方法中调用androidManifest.SetHardwareAccel() 方法。

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"));
}
}

然后再使用gradle打包,一切都完美了。

总结:

​ 其实这个方案的原理很简单: Unity在使用gradle生成AndroidManifest之后,build apk之前会回调OnPostGenerateGradleAndroidProject(string basePath)方法,此时对AndroidManifest做任何操作都不会再被覆盖了,不光android:hardwareAccelerated,其他任意一切我们都可以修改。

但是这个简单的方案却需要对API相当熟悉,国外这位老哥向我展示了真正的技术,这里我搬运过来分享给其他那些一样被同类问题困扰的猿们,看到就是猿粪!同时也感谢stackoverflow上的pale bone老哥不吝惜分享技术,这里挂上stackoverflow 上的问题链接以示感谢。

https://stackoverflow.com/questions/45820447/unity-force-android-hardware-acceleration

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342