【问题标题】:Targeting Android with Scala 2.8 Trunk builds使用 Scala 2.8 Trunk 构建以 Android 为目标
【发布时间】:2011-02-15 05:29:27
【问题描述】:

在 android 上使用 Scala 的权威参考似乎在这里:http://www.scala-lang.org/node/160

不幸的是,所有关于在 android 中使用 scala 的参考资料都基于 Scala 2.7,并引用了自定义构建 android-library.jar,其中有几个隐晦的引用表明更高版本的 android 不需要此自定义构建(我使用的是 2.1 / API v7)

那么...在 android 项目中使用 Scala 2.8 需要哪些步骤?最好使用 Eclipse 和 Google 为该 IDE 提供的 Android 工具。

【问题讨论】:

  • 我刚刚更新了我的答案 - 现在有一个 Eclipse 插件。

标签: android scala scala-2.8


【解决方案1】:

编辑:

我这样做的新方法是使用我的 Eclipse 插件:https://github.com/banshee/AndroidProguardScala(自述文件有安装说明和指向正常 Eclipse 更新站点的指针)。

旧答案仍然有效,但新方法更好。

[老办法] 我的做法:

  • 使用普通的 Android/eclipse 工具创建 Java 项目。
  • 添加第二个包含 Scala 代码的项目。这样我就可以保留生成的代码以供将来参考(我是 Android 和 Scala 的新手)。本项目可以引用android.jar。
  • scala 项目生成一个用于 java 项目的 jar 文件
  • 使用 proguard 剥离库。我相信这避免了对 2.7 中使用的 scala-android.jar 的需要

不过,我还没有将它用于比 hello, world 更雄心勃勃的事情,所以更多地把它当作一组提示。

在 scala 项目中,我添加了一个构建器(Builder > New),它只是一个名为 pguard 的 shell 脚本,位于项目的根目录中,其中包含:

#!/bin/sh
cd $1
PROGUARD=$HOME/dev/proguard/lib/proguard.jar
LIBS=
OUTPUT=lib/proguard.jar
rm -f $OUTPUT
AJAR=/Users/jamesmoore/dev/android-sdk-mac_86/platforms/android-7/android.jar
# java -jar $PROGUARD -injars 'bin:lib/scala-library.jar(!META-INF/MANIFEST.MF,!library.properties)' -outjar $OUTPUT -libraryjars  @proguard.txt
java -Xmx1g -jar $PROGUARD -injars 'bin:lib/scala-library.jar(!META-INF/MANIFEST.MF,!library.properties)' -outjar $OUTPUT -libraryjars $AJAR @proguard.txt

构建器将位置设置为:

${build_project}/pguard

并且工作目录和参数都设置为

${build_project}

在 scala 项目的根目录下,还有一个 proguard 参数文件 @proguard.txt:

-dontwarn
-dontoptimize
-dontobfuscate
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
                SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-keep public class com.banshee.** {
    public protected *;
}

当然,您需要更改 -keep 参数以保留您自己的代码。

在 java 项目中,我添加了由 scala 项目生成的 jar 文件(我在上面的脚本中使用了 lib/proguard.jar)。

但是,不要将 scala 项目作为必需项目添加到 java 项目的构建路径中。这将在 jar 文件之外添加 scala 类文件并混淆 dex(因为它会同时获得 .class 文件和 jar 中的相同内容)。据我所知,Eclipse 将在工作区中构建所有内容,因此当您点击 go 按钮时,两个项目都会构建。

【讨论】:

  • 有趣...如果这也适用于“Scala”项目中的 android.jar,那么您自己就有了一个可以接受的答案:)
  • 是的,它应该可以工作——我的配置确实在 scala 项目中使用了 android.jar。上面代码中的“-libraryjars $AJAR”位告诉proguard查看android.jar,但不要在jar中包含任何android代码;这将由主项目处理。
  • 不错的解决方案,但它阻止了我有效地使用资源。不过,我找到了一种使用 ant 的方法......
  • 我接受是因为它是一个好的、有效的答案,而且它具有一定的优雅性。这不是我的最终解决方案,但我不认为这是否认你观点的有效借口:)
【解决方案2】:

经过大量调查,看起来 Proguard 确实对于将应用程序部署的大小和速度保持在合理水平至关重要。

遗憾的是,没有合适的方法将 proguard 作为构建步骤嵌入。使用脚本可能是可能的,但我还需要支持 Windows、Linux 和 OSX 环境。

我也不确定双项目解决方案,因为它阻止了 Scala 代码使用生成的资源文件 R.java,而我希望能够这样做。

最后,我能够让 SBT 和 Ant 都使用 Scala 2.8 构建一个 android 2.1 应用程序。 Ant 是最受欢迎的最终解决方案,因为它使用与 Android 的 eclipse 插件相同的文件组织。我在这里写了解决方案:http://scala-ide.assembla.com/wiki/show/ae55a-oWSr36hpeJe5avMc/Developing_for_Android

Eclipse 然后启动 Ant 作为外部工具来打包和安装应用程序。

【讨论】:

  • 我认为这两个(没有 R 访问权限;Windows)都是可以解决的问题。对于 R(以及您想用 Java 编写的任何其他内容):在 scala 项目中,您只需将 Java 项目 bin 目录添加到 Scala 项目(打开项目属性,转到 Java Build Path,添加 YourJavaProject/bin)。对于 proguard 构建阶段:它不必是脚本。我现在在 OSX 和 Windows 上运行;只需将所有内容移入@proguard 文件即可。
  • 听起来可以工作,但它也引入了两个项目之间的循环依赖。在这种情况下,这不应该是一个问题,但它仍然让我感到紧张
【解决方案3】:

我现在使用对我之前答案的修改来在 Windows 上运行:只需将所有内容移动到 @proguard_windows.txt 中,这样您就不必担心作为脚本运行。

我的新@proguard_windows.txt 看起来像:

-injars bin;lib/scala-library.jar(!META-INF/MANIFEST.MF,!library.properties)

-outjar gen/scandroid.jar

-libraryjars lib/android.jar

-dontwarn
-dontoptimize
-dontobfuscate
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
                SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-keep public class com.banshee.** { public protected *; }
-keep public class org.xml.sax.EntityResolver { public protected *; }

请注意,在 Windows 中,您需要为 -injars 使用分号。讨厌。

构建器如下所示:

(running cygwin here, so the cat option path takes a slash)
James@Greine:/cygdrive/c/Users/james/workspace/Scala2$ cat .externalToolBuilders/proguard.launch
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\Windows\System32\java.exe"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Xmx1g -jar lib/proguard.jar @proguard_windows.txt"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${build_project}"/>
</launchConfiguration>

您需要将其放入 .externalToolBuilders/proguard.launch。

这里有趣的是它只是一个 java 命令,而不是任何类型的 shell 脚本,所以在 Windows/Mac 之间移植相当容易(我假设是 Linux,但还没有这样做),因为您只是在更改实际 java 二进制文件的位置。

(将其作为新答案提交,因为它与被标记为正确(ish)答案的答案有点不同)

【讨论】:

  • 成功!仅供参考,您需要将android sdk中的android.jar和scala的lib目录的全部内容(好吧,也许不是全部内容,但不仅仅是android-library.jar)添加到scala lib项目目录中,以便proguard正常工作。然后将你的android项目的bin目录添加到你的scala项目的类路径中,并将你的scala项目中的gen\scandroid.jar添加到你的android项目的类路径中。然后你可能需要多次构建才能解决循环依赖(它不是真正的循环依赖,因为 R 类不依赖于 scala proj。
  • 澄清:提到的循环依赖是:Android 项目的 gen 文件夹不依赖任何东西 -> Scala 项目依赖于 android 项目的 gen 类 -> Android 项目依赖于 scala 项目的 scandroid.jar。理想情况下,这只适用于一个项目(为什么不呢?)。
  • 我几乎让单项目 proguard 设置工作,但我遇到了 proguard 问题,包括 scandroid.jar 中的 R 类。如果您知道如何排除类文件(相对于 jar 文件),请回答这个问题:stackoverflow.com/questions/2885852/…
【解决方案4】:

我一直在使用 Proguard 在 Eclipse/ADT 构建中对 Scala 库进行 treeshake,但它还有很多不足之处。它很慢,而且会弄乱其他 .class 文件,因此您必须经常重建项目。

受这些问题和 Android 问题跟踪器中的一些问题的启发,我制作了另一个工具(基于 Jar Jar Links),现在我用它来摇动 scala 库。通过这个构建步骤,我实际上对整个 Eclipse+ADT Scala 在 Android 上的情况相当满意。也许它也对你有用,试一试,它可以从http://code.google.com/p/treeshaker/获得。

【讨论】:

    【解决方案5】:

    如果您习惯使用 Gradle 构建工具,那么 Gradle 的 Android 插件可以让整个过程变得非常简单。见:https://github.com/jvoegele/gradle-android-plugin/wiki

    【讨论】:

    • 如果 gradle 是一种选择,那么 SBT 也是一种选择——而且我已经成功地使用了 SBT。这里真正的问题是外部构建系统和 eclipse/android 插件所期望的不同目录结构。
    猜你喜欢
    • 2011-03-28
    • 2011-04-09
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    相关资源
    最近更新 更多