最近在使用unity2017时,因渠道方要求,给出的包必须要是target21,在直接修改了buildsetting中的target APILevel为21后,然后将项目的androidmainfest的targetsdkversion设置为21,打包时出现了如下报错。
[Temp\StagingArea\AndroidManifest-main.xml:2, \Temp\StagingArea\android-libraries\unity-android-resources\AndroidManifest.xml:1] Main manifest hasbut library uses targetSdkVersion='26'
temp文件夹是在unity编译的时候自动生成的临时文件。因为unity在打包过程中会自动合并所有plugins目录下的androidmainfest生成一个唯一的androidmainfest。对于合并后的唯一的targetsdkversion的设置,首先取决于buildsetting中的target APILevel,其次是androidmainfest中的设定。
比如我设置了buildsetting中的target APILevel为21,而我有一个androidmainfest的taegetsdk为26,就会出现以上报错。高版本无法和低版本合并。
但我的项目中只存在一个androidmainfest,且设置为21,但仍出现了已上报错。于是我打开了报错信息中的\Temp\StagingArea\android-libraries\unity-android-resources\路径,发现在项目编译的时候,在这个路径下自动生成了一个androidmainfest。且里面只存在一句话:
正是因为这个生成的androidmainfest里的设定targetsdk版本过高导致了无法合并。因此我去unity官网查询了unity-android-resources这个编译时生成的目录。
官网对这个目录的生成有着详细的解释 : Unity必须将plugins目录下的'res'文件夹中的所有文件构建到一个插件中。该插件称为unity-android-resources,简而言之就是当出包的时候,如果plugins/android目录下存在res这个文件夹,unity就会为了编译这个文件夹中的资源将它当做一个插件来调用,就将res中的文件编译成一个叫做unity-android-resources的文件,自动为它生成一个androidmainfest,里面默认的targetsdkversion是26。这个可以说是unity的bug
但官网并不鼓励这种在plugins/android目录下直接放res文件夹,称这是已经被弃用的功能。但是现在时间紧迫,我也不可能为了出包就删掉这个res目录,因此经过一番研究,发现了针对这个问题的几个解决办法:
1.res目录之所以存在是因为项目中使用的某些jar包需要去调用它,而在某个版本的unity之后,官网鼓励开发者去使用aar包来代替jar包,而aar包最大的好处就在于可以直接将资源也放进去,当我们使用androidstudio去打出一个aar包,就可以直接将res文件设置好,打出的aar包中自然就带上了res文件,那么unity就不需要存在这个文件夹了。具体aar包的出法这里不再解释,网上有很多资料。
2.unity在编译unity-android-resources时之所以默认是26,是因为我们没有对他进行设置,而具体设置是办法就是,在res这个目录下创建出一个文件叫做project.properties。(随便创建一个文本文档改后缀名就可以),然后再这个文件里的内容是
target = android-21
android.library = true
这样的话在每次打包时就会将生成的androidmainfest设置为21,也可以根据自己的实际情况来设定targte的值。这样就能完美解决这个问题了。
补充:发现这种方法在unity的build system为internal时不会起效,只会在build system为gradle时会被编译后起效。
3.当我们使用gradle出包时,将target APILevel设置为最高忽略掉这个问题,并在最后的gradle.build文件中去处理targetsdk的设置,这样可以完美避免以上情况。具体的步骤已经有大佬给出
https://blog.csdn.net/geoffyan/article/details/79761051
4.出于某种gradle编译后的bug,导致我无法使用gradle打出可以使用的工程,这时仍要使用internal去编译解决问题。因此我还是推荐使用aar包来解决该问题。(如果res目录并不重要,可以直接删除掉res目录来避免这个问题)。