Skip to main content

Targeting Android with Scala 2.8 Trunk builds



The definitive reference for using Scala on android seems to be here: http://www.scala-lang.org/node/160





Unfortunately, all the references on using scala with android are based around Scala 2.7 and refer to a custom build android-library.jar, with a couple of cryptic references suggesting that this custom build isn't needed for later versions of android (I'm using 2.1 / API v7)





So... What are the steps needed to use Scala 2.8 in an android project? Preferably using eclipse and the Android tools that Google supplies for that IDE.


Comments

  1. Edit:

    My new way of doing this is to use my Eclipse plugin: https://github.com/banshee/AndroidProguardScala (the readme has instructions for installing and a pointer to a normal Eclipse update site).

    The old answer still works, but the new way is just better.

    [The old way]
    My approach:


    Use the normal Android/eclipse tools for creating a Java project.
    Add a second project containing the Scala code. That way I get to keep the generated code for future reference (I'm new at both Android and Scala). This project can reference android.jar.
    The scala project produces a jar file that's used in the java project
    Use proguard to strip the library. I believe this avoids the need for the scala-android.jar that was used in 2.7


    I haven't used this for anything more ambitious than hello, world though, so take it as more of a set of hints.

    In the scala project, I add a builder (Builder > New) that's just a shell script called pguard in the root directory of the project containing:

    #!/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


    The builder has Location set to:

    ${build_project}/pguard


    And both working directory and arguments set to

    ${build_project}


    Also in the root of the scala project, there's a proguard arguments file @proguard.txt:

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


    You'll want to change the -keep arguments to keep your own code, of course.

    In the java project, I add the jar file that's produced by the scala project (I use lib/proguard.jar in the script above).

    Don't add the scala project as a required project in the java project's build path, though. That will add the scala class files in addition to the jar file and confuse dex (since it'll get both the .class files and the same things in the jar). As far as I can tell, Eclipse will build everything in the workspace, so when you hit the go button, both projects get built.

    ReplyDelete
  2. After much investigation, it really does look like Proguard is essential to keep the size and speed of deploying the application to reasonable levels.

    Sadly, there is no suitable way to embed proguard as a build step. Using scripts might be a possibility, but I also need to support Windows, Linux and OSX environments.

    I was also unsure about the twin-project solution, as it prevented Scala code from using the generated resources file R.java, which I wanted to be able to do.

    In the end, I was able to make both SBT and Ant build an android 2.1 application using Scala 2.8. Ant was the favourite final solution as it works with the same file organisation as Android's eclipse plugin. I've written up the solution here: http://scala-ide.assembla.com/wiki/show/ae55a-oWSr36hpeJe5avMc/Developing_for_Android

    Eclipse then launches Ant as an external tool to package and install the application.

    ReplyDelete
  3. I'm now using a modification of my previous answer to run on Windows: just move everything into @proguard_windows.txt so you don't have to worry about running as a script.

    My new @proguard_windows.txt looks like:

    -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 *; }


    And note that in windows, you need to use a semicolon for -injars. Nasty.

    The builder looks like this:

    (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>


    You'll want to put this in .externalToolBuilders/proguard.launch.

    The interesting thing here is that it's just a java command, not any kind of shell script, so it's fairly easy to port between Windows/Mac (and I'm assuming Linux, but haven't done that yet), since you're just changing the location of the actual java binary.

    (Submitting this as a new answer because it's a bit different than the one that got marked as the correct(ish) answer)

    ReplyDelete
  4. I have been using Proguard to treeshake the Scala library in Eclipse/ADT builds, but it leaves a lot to be desired. It's slow and it messes up the other .class files, so you have to rebuild the project more often than not.

    Inspired by these questions and some of the issues in the Android issue tracker, I have made another tool (based on Jar Jar Links) which I now use to treeshake the scala library. With this build step I'm actually fairly happy with the whole Eclipse+ADT Scala on Android situation. Maybe it'll work for you too, give it a spin, it's available from http://code.google.com/p/treeshaker/

    ReplyDelete
  5. If you are comfortable using the Gradle build tool, then the Android plugin for Gradle makes this whole process extremely simple. See: http://wiki.github.com/jvoegele/gradle-android-plugin/

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex