For my little pet project Akka-Mobile I need to run Scala on Android. In theory this is dead simple. However in practice there are some issues. When you simply add the Scala runtime library to an Android project you will get an error during dexing. The reason is that the Scala runtime library is just too large. The way to get around this issue is to remove the class-files which aren’t required by your application. This is usually done with Proguard.
The Build Script
So you need to include Proguard in your build script. There are different ways to do it. I tried several existing build scripts from different people with mixed results. Finally I’ve settled with a script from here. This site contains a description and steps you need to take.
Of course you need to set the right paths in the local.properties file on your dev machines. For example on mine:
Note that Proguard doesn’t like spaces and other special characters in file paths. I had trouble initially because of that. You either can ensure that everything is properly escaped or that you put everything in an appropriate location.
I also added a newer version Proguard to my project, because the version shipped with Android had some bugs. So in the build.properties I have:
That’s all. Of course I’ve done some project specific modifications to the original build file. Anyway, when you follow the instructions of the original page you should be fine.
The IDE Setup
Of course the build script is only half the story. I want to use my IDE to edit and debug the code. I’m an IntelliJ user, so this is my IntelliJ setup. (I should check out Eclipse’s Scala support, I’ve heard that they put a lot of effort into it).
First create (or import) the project like a regular Android project. Then also add the Scala facetted to the project. Now in theory you can compile and run that project. Unfortunately the dexing step will fail due to the large Scala runtime.
Basically you need to replace the build step with your costume build step. I ‘unchecked’ the ‘make’ step in the run configuration and added an Ant step. Like this:
You can run any Ant target which builds the .apk for you. The only thing you need to ensure is that IntelliJ finds the apk-file. I created a special ‘debug-install’ target which compiles the project and copies the apk to the location where IntelliJ usually puts it. An alternative would be to configure IntelliJ to use your location. Here’s the Ant-Task for my IDE debugging:
After these steps everything should run in IntelliJ. When you use Run / Debug the Ant script will build the apk and IntelliJ will load it into the Emulator / Phone. Afterwards it just attaches to the process like normal. Everything should work, like the debugger etc.
Update For Android 4.0 SDK
With the 4.0 SDK the standard Android build file has changed, so that the original script above doesn’t seem to work anymore. You will get an error telling you that the build script is outdated. Here’s what I’ve done to get it to run:
- I followed the instructions of the error message. I deleted the existing build.xml and then upgraded the project with: ‘android update project –path ./’. (You need the android tools path in your PATH variable. Or use the complete path to the ‘android’ command of your SDK).
- Then I re.added my Scala tasks in the build.xml:
- Unfortunately the ‘build-scala.xml’ file still had issues with the new SDK. I fixed two things. First the ‘compile-scala’ task new depends on ‘-compile’ instead of ‘compile’. I also removed the ‘<src refid=”project.libraries.src”/>’ entry. Looks like this property isn’t there anymore, but it wasn’t used anyway in my project. The compile-scala task look now like this:
- I added the property ‘manifest.package’ which holds name of the top package. Looks like this property isn’t defined anymore by the standard build. This property is used for Progard to keep those classes in your project. So for my project the ‘ant.properties’ file now looks like this:
- The last change I’ve done is in the ‘-post-compile-scala’ task. Here the ‘build.mode.debug’ and ‘build.mode.release’ flags are no longer set. Instead the ‘build.target’ property contains the build type. So I’ve changed that in the ‘-post-compile-scala’ task:
Second & Third Update
First I’ve fixed another thing above so that debugging works with the Android 4.0 SDK. Then I’ve created an example project which should work with the Android 4.0 SDK and incorporates all my changes as explained above. Then Patrick Boos improved that even further. Thanks a lot. You can find the example project on GitHub (https://github.com/pboos/scala-on-android-example#readme) . Don’t forget to fix the local.properties for your environment. And remember that Proguard doesn’t like spaces in paths. My build file won’t work with spaces in file paths right now =(.
That’s it for now. If you know a better way, have tips or problems: Tell me =).
- Athena: Goddess of War
- Akka-Mobile: Unreliable Connections, Push-Messages