Scala / Android项目中的“多个scala库”

时间:2013-04-24 16:17:45

标签: android eclipse scala libgdx proguard

我在eclipse中有一个libgdx android项目,我已经添加了scala和AndroidProguardScala性质。 这很好用,但突然eclipse开始给我警告“在构建路径上找到多个Scala库”。我仍然可以在设备上构建和安装项目,但它会立即退出使用NoClassDefFoundError: scala.Tuple2$mcZZ$sp所以看起来根本没有包含Scala库。

我的项目似乎将Scala库放在“Scala Library [2.10.1]”(作为“scala-library.jar”)和“Android Dependencies”下(作为“scala_library.min.jar”) )所以我猜Proguard输出与原始库相冲突,但我不知道为什么会发生这种情况或者如何修复它。

此时我可以创建一个新项目并将源文件复制过来,但如果有人能够对此有所了解,那就太棒了。

编辑:经过一些实验后发现,这段代码(来自特质方法)似乎导致了问题。

acckeys match {
  case (true, false) => acceleration.set(0, accel).rotate(rotation)
  case (false, true) => acceleration.set(0, -accel).rotate(rotation)
  case _ => acceleration.set(0, 0)
}

(其中acckeys是一个返回tupleacceleration为向量的函数)

多个库警告仍然存在,所以我猜这与问题无关。幸运的是,我实际上并不需要从项目的android版本中引用此代码,但知道此代码编译但无法运行的原因仍然很有用。

2 个答案:

答案 0 :(得分:0)

我确切地知道你遇到了什么问题。这与AndroidProgaurdScala无法识别主项目中的类文件有关。结果是,包含了在android项目中定义的任何类,但是任何“新的”类,例如你的元组都将丢失,因此你会得到精彩的NoClassDefFoundError。我没有遇到“在构建路径上找到多个Scala库”的警告,但这可能意味着您已将scala特性添加到项目中,并且还在其上添加了library.jar。尝试撤消您的配置并按照我下面的内容进行操作;否则,请按照以下步骤设置新项目并复制您的来源。

我发现Scala Nature和Android Proguard Scala在运行渣土后有点痛苦。我不是100%肯定你能够抢救现有的项目,但我们可以试着看看会发生什么。首先,从项目中删除所有与scala相关的性质,并将它们恢复到初始状态,这些状态只适用于普通的Java项目。

让我们一起使用Scala设置libGDX,看看出了什么问题:

  1. Make sure your environment is setup correctly.(注意:您需要获取最新版本)
  2. Set up the libGDX project as normal.(或在您的案例中使用现有项目)
  3. 右键单击android项目,“添加Scala自然”,然后“添加AndroidProgaurdScala自然”
  4. 右键单击主项目“添加Scala nature”
  5. 右键单击桌面项目“添加Scala nature”
  6. 现在,这可能已经到了你的位置,但仍然存在AndroidProgaurdScala的问题,不知道你的主项目中有哪些类。它似乎忽略了包含的项目,并没有将它们添加到scala_library.min.jar。为了解决这个问题,我找到了一个效果很好的解决方案:

    1. 右键单击Android Project>属性> Java构建路径
    2. 转到“项目”标签,删除主项目。我知道这是违反直觉的,但请相信我。
    3. 转到来源标签>链接来源......
    4. 导航并从主项目中选择“src”文件夹
    5. 按OK
    6. 清理并重建项目。
    7. 此设置我已经过广泛测试和使用,没有任何问题。 Android和桌面版本都很开心,并且在没有Scala或混合代码的任何投诉的情况下工作。 android项目现在完全了解您在主项目中使用的所有Scala类,因为源现在被复制到android项目的构建中。 (即没有NoClassDefFoundError出现与Scala相关的任何内容)。

答案 1 :(得分:0)

当我的Proguard配置文件出现问题时,我收到了类似的消息。你可能会检查:

  • Proguard正在运行
  • 您的配置文件包含:-keep public class **。YourPackage。**或类似的东西
  • 您的配置文件已针对Scala库进行了修改,例如

    ## SCALA SETTINGS
    
    -dontwarn **$$anonfun$*
    -dontwarn scala.android.**
    -dontwarn scala.beans.ScalaBeanInfo
    -dontwarn scala.collection.generic.GenTraversableFactory
    -dontwarn scala.collection.immutable.RedBlack$Empty
    -dontwarn scala.concurrent.forkjoin.**
    -dontwarn scala.reflect.**
    -dontwarn scala.sys.process.**
    -dontwarn scala.tools.**,plugintemplate.**
    
    
    #(org.xml.sax.EntityResolver)Class.forName(variable).newInstance()
    -dontnote org.xml.sax.EntityResolver
    
      #(org.apache.james.mime4j.storage.StorageProvider)Class.forName(variable).newInstance()
    -dontnote org.apache.james.mime4j.storage.DefaultStorageProvider
    
    -dontnote scala.android.app.Activity
    
    
    -keep class scala.android.package**
    -keep class * extends scala.android.app.Activity
    
    ## Fixes ==> Warning: ... can't find referenced class sun.misc.Unsafe
    -libraryjars D:\Program Files\Apache\m2\repository\com\google\code\findbugs\jsr305\2.0.1\jsr305-2.0.1.jar
    -dontwarn sun.misc.Unsafe
    
    
    -keep class * extends scala.runtime.MethodCache {
        public ;
    }
    
    -keepclassmembers class * {
        ** MODULE$;
    }
    
    -keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool {
        long eventCount;
        int workerCounts;
        int runControl;
        scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack;
        scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack;
    }
    
    -keepclassmembernames class scala.concurrent.forkjoin.ForkJoinWorkerThread {
        int base;
        int sp;
        int runState;
    }
    
    -keepclassmembernames class scala.concurrent.forkjoin.ForkJoinTask {
        int status;
    }
    
    -keepclassmembernames class scala.concurrent.forkjoin.LinkedTransferQueue {
        scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head;
        scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail;
        scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe;
    }