Unity 使用多个 Android 插件与二次开发

本文的写作时间距今已久,其中涉及到的 API 可能发生了较大的变化,且 Unity 集成 Vuforia 已有了官方支持。本文的解决方案可能不再适合您当前遇到的问题,请酌情谨慎参考。

利用 Unity 开发 Android 应用时往往需要调用 Android 原生开发的方法,或是导出 Android 工程进行二次开发。单独一个问题很容易就能在互联网上找到答案,但当需要导入多个 Jar 包( Android 原生方法通过打成 Jar 包在 Unity 工程中使用)、又需要导出 Android 工程继续开发时,就有可能遇到问题了。

本文记录了解决过程。想看结论及解决方案可以直接拉到最后。

本文所述的解决方案不具有普适性

场景

场景来源于一个实际面对的任务,即在「使用高通 Vuforia 的 Unity 工程」中「调用 Android 方法(即引入新的 Jar 包)」,并「接入 KTPlay 的 SDK 」。由于 Vuforia 的 Unity SDK 本身就引入了 Jar 包,若引入新的 Jar 包,就会牵涉到如何修改共同的 XML 文件,如何处理和已有 Jar 包的关系等问题。而后者 KTPlay 的接入需要 Unity 工程导出 Android 工程继续开发。这本来并不会有问题,但事实上 Unity 使用了 Jar 包后进行二次开发的确会出现一些变化。当然这也是因为我半吊子水平,对 Unity 和 Android 开发都不够了解。不过总会有这样的时候,人也是这样过来的,网上难以轻易找到的东西,总归做个记录有利无弊。

使用第二个 Android 插件

Unity 调用单个 Android 插件的方法其实网上都找得到,主要的思路是新建一个 Android 工程,在里面编写好方法后,打成 Jar 包放入 Unity 的插件文件夹中。然后利用 Unity 中的 AndroidJavaClass 来调用 Android 工程中的方法。但是在 Vuforia 工程中本身已经用到了 Android 插件,如果把新的内容覆盖进去,别的倒是没什么,但是 AndroidManifest.xml 文件却会被覆盖掉。这个文件是对 Android 应用很关键的配置文件, Vuforia 插件显然也用到了这个文件,将其覆盖掉明显是不行的。

于是我开始搜索网上的解决方案。一开始搜索的是如何在 Unity 中导入2个 Jar 包,但根本无法找到答案。倒是很多此类问题中提到了他们要解决的也是关于 Vuforia 工程导入 jar 包的问题,这启发了我,最后在 Vuforia 的官网文档中找到了官方撰写的教程。这对我也是一个启示,搜索问题时要先 specific 再 general 。

我的解决参考了 官方文档这篇文章 (讲的是通常调用 1 个 Jar 包的情况)。两篇文章都挺好,就是由于作者和读者的思路问题在细节上理解容易出偏差,我是综合了两篇文章并自己试验后最终成功的。

具体可以顺着官方文档来,首先新建工程,但是注意新建工程的包名要与 Unity 工程导出 Android 应用时使用的包名一致,这会省很多麻烦。官方文档似乎没说明这一点。然后导入 Unity 和 Vuforia 相关的 Jar 包。注意 classes.jar 随 Unity 版本的变化,放置的位置也有区别,需要自己找一找。编写完以后需要导出 Jar 包,在工程属性中勾选 isLibrary 然后可在工程目录中找到自动生成的 Jar 包。然后把 Jar 包复制到 Unity 插件目录下,并修改 Unity 目录下 AndroidManifest.xml 文件中的主 Activity 名。(不能直接覆盖这个xml文件,因为 Vuforia 在里面也有些配置)。以上两步官方文档都说的很好,不过它用的是一个简单的 toast 的例子。实际我们开发时往往还会用到一些第三方的 Jar 包、 so 文件等,因此也要把这些文件也放入 Unity 插件目录对应位置下;使用这些东西导致的 AndroidManifest.xml 文件修改(如增加权限等)也需要在 Unity 目录下 AndroidManifest.xml 文件中对应修改。如果有素材变动啥的最好把 res 文件夹也复制过去。这里官方文档就说把 Jar 包放过去,可能是觉得这些都是常识性问题吧,我说的就比较细了,新手说不定觉得那些第三方的 Jar 和 so 都打包进自己的 Jar 了呢?(虽说看文件大小还是很容易判断的)

顺便一提,如果你自己的 Jar 用到了第三方的 Jar 包,那么做完导入 Unity 后那些第三方 Jar 包的地位和 Vuforia 的两个 Jjar 包目测是平等的。而我们在开发自己的 Jar 时并没有用到 Vuforia 那两个 Jar 包的东西,是不是说明如果我们不用 Vuforia 那两个 Jar 包里的东西,不导入那两个 Jar 包也没事?待测试。

还有,至于我说为什么没有普适性,因为我们是用自己的包名、主方法名取代了 AndroidManifest.xml 原来的相应内容,看来 Vuforia 的两个 Jar 包并不需要这两个东西。因此这两个 Jar 包和我们自己写的 Jar 包有很大的区别。虽然如此,应该不会有个第三方 Jar 包需要让你修改这些才能加进去吧……

加入插件后的二次开发

其实就是关于 KTPlay ,这个游戏内社区总的来说挺好用的。接入 Unity 的过程比较奇葩,首先要在 Unity 中做相关的配置,然后还要导出 Android 工程,在主 Activity 的 onStart 等一系列方法中加入相关的代码。其实也很简单,我试验的时候也很顺利,以至于当我把导入插件后的实际项目再拿去加入 KTPlay 却发现毫无反应时,大脑简直一片空白,连大概的可能性都猜不出。后来还是顿悟了,因为测试后发现不是 KTPlay 有问题,而是二次开发加入的相关代码根本没有被执行,然后就想到了,当之前加入 Android 插件后,这个应用的主方法已经不是那个 UnityActivity 了,而是自己编写的插件中的那个 Activity (由于之前更改了 AndroidManifest.xml )。于是问题解决。

当然这样就十分有趣了,因为我编写插件在前,引入 KTPlay 在后,也就是说没引入 KTPlay 之前就加入了它的相关代码。当然这并不是一件坏事,事实上反而是一件好事,因为这样你可以直接在 Unity 中打包 apk 了,而不用再使用蛋疼的 Eclipse 。KTPlay 可以考虑下这样的用法啊。

总结

对于此类需要在 Unity 中使用多个 Android 插件,并进行二次开发的问题,需要注意:

  1. 新建 Android 插件的工程时,确保包名与 Unity 导出 Android 的包名一致。
  2. 导入 classes.jar 和其他 Unity 插件工程下的 Jar 包和 so 文件。
  3. 事先观察需要二次开发的内容,把二次开发需要在主 Activity 中改动的地方事先改动好(主 Activity 就是你现在写的插件的 Activity)。
  4. 工程属性下勾选 isLibrary 导出 Jar 包。
  5. 把导出的 Jar 包和你开发插件过程中另外用到的第三方 jar 包和 so 文件复制到 Unity 工程的相关目录下。 res 文件夹也复制过去。
  6. 相应修改 AndroidManifest.xml (而不是粗暴覆盖原有的文件)。
TAGS:  UnityAndroidVuforiaKTPlay
正在加载,请稍候……