Android升级ADT22后会报ClassNotFoundException的原因分析

2013/07/18 14:13
阅读数 126

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

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

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

问题解决了,但为什么要这么做呢?之前ADT21为何又不需要呢?我另一台机器使用的还是ADT21,因此我把两个版本的ADT工程属性比较了一下,发现还真不一样。下面这个是ADT21的:

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

显然,ADT21把所有引用的JAR包都归纳为Android Dependencies,而ADT22是自动将JAR分成Android Private Libraries和Android Dependencies两类了。ADT21不需要勾选Export就能自动将所有引用的JAR包导出并打包到APK,而ADT22则给开发人员选择权限,让开发人员自己决定哪些包要导出到APK里。比如程序面向的是高版本的Android系统,可以选择不需要导出低版本的某些支持包。

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

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

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

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

展开阅读全文
打赏
0
0 收藏
分享

作者的其它热门文章

加载中
杨鬼博主
原来是ADT21的.升级后发现classnotfound异常了.百度了下.找到这篇文章后.按照上文的办法解决了.谢谢原文作者.转载下.
2013/07/18 14:15
回复
举报
更多评论
打赏
1 评论
0 收藏
0
分享
返回顶部
顶部