Android升级ADT22后会报ClassNotFoundException的缘由分析

最近有个同事跟我报怨说,他的系统重装Eclipse使用新的ADT22后,编译的android apk运行总会报ClassNotFoundException错误。我说这怎么可能,谷歌这么大的公司出来的东西怎么可能有这种问题。他说不信你试试,我说试试就试试。我以前用的是ADT21,结果升到ADT22后一运行,晕,不得不服,还果然是ClassNotFound了。 android

接下来我又换了几个工程编译运行,发现并不必定是全部工程都有错,而是部分使用了第三方JAR包或库工程的APK才会出错,也就是说,NotFound的Class都是在引用的JAR包里的。 eclipse

接下来天然是在网上找解决办法了,最后也找到了,就是在.classpath里给com.android.ide.eclipse.adt.LIBRARIES加exported=true,或者在工程属性Java Build Path的Order and Export里勾选Android Private Libraries,将相关的库导出到APK里。 ide

问题解决了,但为何要这么作呢?以前ADT21为什么又不须要呢?我另外一台机器使用的仍是ADT21,所以我把两个版本的ADT工程属性比较了一下,发现还真不同。下面这个是ADT21的: 工具

其中相互对应的包和源码我用红线相连起来了以便分析。下面这个是ADT22的: ui

显然,ADT21把全部引用的JAR包都概括为Android Dependencies,而ADT22是自动将JAR分红Android Private Libraries和Android Dependencies两类了。ADT21不须要勾选Export就能自动将全部引用的JAR包导出并打包到APK,而ADT22则给开发人员选择权限,让开发人员本身决定哪些包要导出到APK里。好比程序面向的是高版本的Android系统,能够选择不须要导出低版本的某些支持包。 spa

显然ADT22比ADT21更合理,用户没勾选的包天然是不该该导出的。但话说回来,其实基本上大部分状况下咱们既然把包加到工程里就是须要导出的。在上图状况下,要达到ADT21版本的导出效果,其实只须要把最后两项勾选上,以下图: .net

这样ADT就会把相应的JAR包里的类也打包到APK里,再运行就不会找不到类了。 翻译

其实要说ClassNotFound这个问题,安卓的开发人员应该都已经不是第一次赶上,在从ADT16升级到ADT17时,就已经搞过一回。再ADT17以前,只要是在工程Build Path里的JAR,无论放在哪,ADT都会自动编译进APK里;但到了ADT17就得把要导出的包全放在libs目录下。为此我还翻译了老外一篇文章,参见:http://blog.csdn.net/huzgd/article/details/7604069blog

从任何JAR都自动导出,到只导出libs目录的JAR,到只导出勾选的JAR,应该说ADT是在改进,但也带来升级的麻烦。总得来讲并非ADT22有问题,而是ADT21以前的编译工具不规范,ADT22只是更规范。就说嘛谷歌不会这么容易使人失望的,但就是会折腾人。 ip

相关文章
相关标签/搜索