具有项目依赖关系的Eclipse / ADT下的Android Activity(解析XY失败)

时间:2011-12-20 20:35:24

标签: android eclipse apk adt multiple-projects

我试图让一个游戏项目与平台无关,所以我把它分成了三个项目从低级别到顶级的android特定级别:引擎,游戏,安卓游戏。

错误中涉及的类/接口是:

  1. (低级别)引擎项目定义了此接口:

    com.myteam.engine.IGame
    
  2. (中级)平台独立游戏项目定义了这些类:

    com.myteam.myproject.Game
    com.myteam.myproject.MyProject (derived from com.myteam.myproject.Game)
    
  3. (顶级)android项目实现活动等:

    com.myteam.myproject.android.MyAndroidActivity (using com.myteam.myproject.MyProject)
    
  4. 所有编译良好并在Windows下完美运行(使用前两个在3级上的另一个Windows项目)。

    但是当使用ADT运行时,它会在Activity启动时在运行时失败。 Android应用程序基本上只显示一个带有“NoClassDefFoundError com.myteam.myproject.MyProject”异常的调用堆栈。

    异常似乎是由于它的超类(或超类'接口)在加载/解析时引起的,因为LogCat输出显示:

    12-20 19:51:51.897: D/ddm-heap(218): Got feature list request
    12-20 19:51:52.207: I/dalvikvm(218): Failed resolving Lcom/myteam/myproject/Game; interface 18 'Lcom/myteam/engine/IGame;'
    12-20 19:51:52.217: W/dalvikvm(218): Link of class 'Lcom/myteam/myproject/Game;' failed
    12-20 19:51:52.227: W/dalvikvm(218): Unable to resolve superclass of Lcom/myteam/myproject/MyProject; (52)
    12-20 19:51:52.227: W/dalvikvm(218): Link of class 'Lcom/myteam/myproject/MyProject;' failed
    12-20 19:51:52.227: E/dalvikvm(218): Could not find class 'com.myteam.myproject.MyProject', referenced from method com.myteam.myproject.android.MyAndroidActivity.onCreate
    12-20 19:51:52.227: W/dalvikvm(218): VFY: unable to resolve new-instance 54 (Lcom/myteam/myproject/MyProject;) in Lcom/myteam/myproject/android/Youcode_AndroidActivity;
    12-20 19:51:52.227: D/dalvikvm(218): VFY: replacing opcode 0x22 at 0x0008
    12-20 19:51:52.227: D/dalvikvm(218): Making a copy of Lcom/myteam/myproject/android/Youcode_AndroidActivity;.onCreate code (88 bytes)
    

    我尝试在其他帖子和论坛中描述的Android游戏项目的“构建路径/顺序和导出”Eclipse项目设置下添加两个第一个项目,但它没有改变。

    我的预感是Manifest或Project设置需要另外提及apk打包或运行时的包/类依赖项。有什么想法吗?

7 个答案:

答案 0 :(得分:12)

我有一个三层Android / Java应用程序,几乎和你一样:

  1. 用于低级别网络通信的仅Java项目
  2. 用于抽象低级项目功能的仅Java项目
  3. Android应用
  4. 上面的每个内容都是一个包含在单个工作区中的独立Eclipse项目。

    以下是您需要做的事情:

    1. 在App的项目属性 - > Java Build Path-> Projects下,添加仅Java项目
    2. 在App的项目属性 - > Java Build Path-> Order and Export下,检查仅限Java的项目(标记它们以便导出)
    3. 现在,您的应用应该构建并运行时不会出现NoClassDefFoundError例外或VFY错误,如下所示:

      03-27 21:10:17.120: W/dalvikvm(420): VFY: unable to find class referenced in signature (Labstractionlayer/BaseStationManager;)
      03-27 21:10:17.120: W/dalvikvm(420): VFY: unable to find class referenced in signature (Labstractionlayer/BaseStationManager;)
      03-27 21:10:17.160: I/dalvikvm(420): Failed resolving Lcom/demo/log/AndroidLogWrapper; interface 253 'Lcommon/Logger/LogWrapper;'
      03-27 21:10:17.160: W/dalvikvm(420): Link of class 'Lcom/demo/log/AndroidLogWrapper;' failed
      03-27 21:10:17.160: E/dalvikvm(420): Could not find class 'com.demo.log.AndroidLogWrapper', referenced from method com.demo.Application.onCreate
      03-27 21:10:17.160: W/dalvikvm(420): VFY: unable to resolve new-instance 218 (Lcom/demo/log/AndroidLogWrapper;) in Lcom/demo/Application;
      03-27 21:10:17.170: D/dalvikvm(420): VFY: replacing opcode 0x22 at 0x0003
      03-27 21:10:17.170: D/dalvikvm(420): VFY: dead code 0x0005-003c in Lcom/demo/Application;.onCreate ()V
      03-27 21:10:17.170: D/AndroidRuntime(420): Shutting down VM
      03-27 21:10:17.170: W/dalvikvm(420): threadid=1: thread exiting with uncaught exception (group=0x40015560)
      03-27 21:10:17.180: E/AndroidRuntime(420): FATAL EXCEPTION: main
      03-27 21:10:17.180: E/AndroidRuntime(420): java.lang.NoClassDefFoundError: com.demo.log.AndroidLogWrapper
      
      BTW,在ADT r17之前,您只需要执行上面的步骤1(添加仅Java项目)。但是从r17开始,您还需要执行第2步(将Java项目标记为导出)。

答案 1 :(得分:2)

将您的依赖项目的名称添加到Android项目的.classpath文件中。 那样:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" path="src"/>
    <classpathentry kind="src" path="gen"/>
    <classpathentry combineaccessrules="false" kind="src" path="/DependentProject1"/>
    <classpathentry combineaccessrules="false" kind="src" path="/DependentProject2"/>
    <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
    <classpathentry kind="output" path="bin"/>
</classpath>

答案 2 :(得分:2)

我一直试图找到这个很久以前的简单解决方案,据我所知,使用依赖库类使ADT导出最终apk的唯一方法是显式添加所有外部lib.jar(从您的其他项目生成)到您的Android项目的构建路径。

当前版本的Eclipse ADT插件具有非常不灵活的预定义构建生命周期(特别是在dexing步骤中),显然它不支持除了这三种类型的Android项目之外的项目分组(经典,库和测试)。换句话说,ADT不知道如何使用构建路径下的常规Java依赖项目构建您的Android项目,并自动将依赖项目生成的lib.jar添加到主项目的构建路径中(即使您将它们添加到Order中)除非您明确地将外部lib.jar添加到其中,否则将导出列表)。假设你将C:\ workspace \ game \ target \ game.jar和C:\ workspace \ engine \ target \ engine.jar添加到你的android-game项目的构建路径中,生成你的dex文件的命令应该是这样的:< / p>

java [-Xmx1024M, -jar, C:\android-sdk-r16\platform-tools\lib\dx.jar, --dex, --output=C:\workspace\android-game\target\classes.dex, C:\workspace\android-game\target\classes, C:\workspace\game\target\game.jar, C:\workspace\engine\target\engine.jar]

如果您计划采用一些外部构建工具来管理项目构建生命周期,我知道Maven在Android构建生命周期中提供了更灵活的配置。它支持多模块项目(项目分组),可以正确处理常规的Java项目依赖。

我的知识基于Eclipse,期待听到来自Android源或其他复杂IDE用户的一些噪音。

从ADT 17.0.0更新:

最新版本的SDK r17与ADT 17.0.0声称现在正确处理此用例:

  

Eclipse特定的更改

     

名为“Library Projects”的动态类路径容器已重命名为“Android Dependencies”,因为它现在不仅包含Library Projects。

     

现在,容器也将填充由Library Projects引用的仅Java项目。如果这些Java项目也引用其他Java项目和/或jar文件,它们将自动添加(也支持通过用户库引用的jar文件)。

     

重要说明:仅当引用设置为在引用项目中导出时才会发生这种情况。请注意,将项目或jar文件添加到项目构建路径时,这不是默认设置。   始终导出库项目(及其libs / * .jar文件的内容)。此更改仅影响仅Java项目及其自己的jar文件。

     

同样,检测并删除重复项(包括项目和jar文件)。

查看changelog

答案 3 :(得分:2)

我找到了这个帖子,它实际上对我有用,只需确保检查dependentproject

Testing Android project with jar dependecies

答案 4 :(得分:1)

我想,中级项目的Java Build路径包括低级项目。您是否检查了那里的低级项目(“订单和导出”选项卡)?否则,低级项目依赖项不会转发到高级项目,不包括APK中的IGame,这实际上会触发失败。

但是,如果您的项目包含特定于Android的资源等内容,则此解决方案AFAIK将无效。

答案 5 :(得分:0)

我怀疑你和你的项目。从我的观点来看,我看到你有一个很好的设计。但是你为什么要使用Build Path / Order and Export?老实说,从我与Eclipse合作的第一天起,我就没有去过那个标签。

要将jar文件导入为库,请使用标签Libraries - &gt;添加外部罐子。

我很抱歉我不了解游戏编程,这只是一个建议:确保您的引擎适合Android支持。例如,Android不支持javax.imageio。如果没有,可以使用外部jar编译应用程序,但可以在运行时崩溃。

答案 6 :(得分:0)

我知道这是一个老问题,但我找到了一种新的方式来解决这个错误,这可能会帮助其他人更新。

我在R.id上使用 switch / case 语句时遇到此错误。 “常量”。最新的更新不再认为R.java声明在代码中是常量,即使它们被声明为final。会发生什么是.apk将编译和安装,但会产生Lcom错误。

要解决此问题(在Eclipse中),请将光标放在开关声明中,然后使用Ctrl + 1将开关转换为列表其他的。请注意,如果在 case 语句中有嵌套符号,则需要重写该代码块(可能需要额外的 else )。