Sunday, August 21, 2011

Scala on Android with Eclipse

Yes, I'm back from the dead. I've been busy starting a company of late and have been pretty much full speed ahead on that, leaving less (read: none) time for blogging.

Anyway, on with the main event: a working setup for developing Android applications in Scala. I spent about 3-4 days total trying to get this setup working, using various different schemes such as the Treeshaker plugin for Eclipse, the Maven Android plugin and others. After hours and hours of fiddling, I finally found a solution that works: a custom SBT setup with the SBT Android plugin. The key is to avoid building the Android app in Eclipse itself, but to use SBT for the heavy lifting.

Eclipse seems to have some very non-deterministic behavior when building applications, especially Android applications. When you add Scala and Treeshaker into the mix, the whole thing falls apart. Furthermore, the build process is very opaque, so it's hard to figure out what is even going wrong, let alone to try to fix it. A build which was fine before might suddenly stop working, raising some exception or simply pegging the processor and making Eclipse totally unresponsive. There doesn't seem to be any pattern to the madness, so it's impossible to fix.

Anyway, as I mentioned, SBT with the Android plugin works beautifully for building apps, but as much as I love Emacs, it is easier to work with Scala in an environment that gives you clear and immediate feedback about type failures and requirements. On the downside, in order to do all of this wonderfulness along with the Android helpers, Eclipse expects a very specific directory layout, and will complain if it does not exist. SBT, by default, uses a completely wacky layout, with the Android manifest files (usually at the root of the project) in src/main/. This means that the actual source code files are in src/main/src/main/java/com/example/.... For a single project without references to other projects, this is unnecessarily complicated and destroys the tiny brain of Eclipse. So the solution is to change SBT's layout to something sane.

Note: I'm using SBT 0.7.x since the SBT Android plugin hasn't yet been ported to 0.10.x

First of all, you need to declare the plugins you will be using (for now just the SBT Android plugin) in project/plugins/plugins.scala. The actual filename doesn't matter, as long as it is in the project/plugins folder. The plugins.scala looks like this:



Standard fare for SBT plugins.

Next is the SBT project file. This is where the magic happens, though there isn't really that much magic to it. It simply changes some paths so that SBT looks in the correct place. Here's the file:



The keys are the five lines in the middle setting the path info. The androidManifestPath assignment causes SBT to look for AndroidManifest.xml in the project root, as do mainResPath and mainAssetsPath. Setting the scala and java source paths to src means that SBT will look in that folder instead of the redundantly redundant src/main/src directory. Finally, overriding aaptGenerateTask simply makes aapt write the generated resource files (R.java and friends) to the gen folder, as the Android Eclipse plugin expects.

With the hard stuff out of the way, you "simply" need to configure Eclipse to use the appropriate builders and classpaths, included in the .project and .classpath files, respectively. Here they are:

.project



and .classpath



Obviously, since the config files include the Scala libraries and builder, you'll need to install the Scala Eclipse IDE. With all of this in place, you should be able to issue a simple sbt start-emulator to build, Proguard, package, deploy and start your application.

Hopefully this post will save you from the pain I endured of trying to get Scala working on the one hand, and the thought of having to use Java on the other.