• 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只是更规范。就说嘛谷歌不会这么容易令人失望的,但就是会折腾人。

  • 相关阅读:
    ps中套索工具怎么使用的方法
    动态加载css方法实现和深入解析
    深入React事件系统(React点击空白部分隐藏弹出层;React阻止事件冒泡失效)
    近期项目中用到的一些自己写的或者整理而成的前端效果干货(********************************)
    Vue.js自定义指令的用法与实例
    vue初探
    React Router基础使用
    javascript常用积累
    js动画(三)
    基于jQuery的ajax系列之用FormData实现页面无刷新上传
  • 原文地址:https://www.cnblogs.com/zsw-1993/p/4879986.html
Copyright © 2020-2023  润新知