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

查了好多资料,发现还是不全,干脆自己整理吧,至少保证在我的做法正确的,以免误导读者,也是给自己做个记录吧!

    最近有个同事跟我报怨说,他的系统重装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只是更规范。就说嘛谷歌不会这么轻易使人失望的,但就是会折腾人。

文章结束给大家分享下程序员的一些笑话语录: 联想——对内高价,补贴对外倾销的伟大“民族”企业。

--------------------------------- 原创文章 By 包和导出 ---------------------------------

原文地址:https://www.cnblogs.com/jiangu66/p/3095492.html