How we use Scala in Bump for Android

This post was written by Will from Bump's server team.

Since Indy's post and Michael and Indy's talk at Scala Days, many of you have been asking about how we used Scala for the Android version of Bump. I'll try to cover a little of the why (without getting to deep into the Scala v. Java battle) and then get into the how. But first, a little background.

As with many startups, we're primarily limited by the number of developers we have working on projects and our Android team was no exception. After releasing 2.0 on iOS, Jamie and I (the server team at the time) had plenty of things we wanted to do to the server, but none of them seemed as pressing as bringing Android up to parity with iOS. Knowing the network stack better than most, we decided that Jamie and I would write the Service while Jake K. and Indy would switch over from iOS and write the Application layer. The final decision ended up being that the Service would be in Scala, whereas the Application would be in Java. So then, why did Jamie and I choose Scala?

Why Scala?

  • It has a lot of functional constructs we're used to and like. We use Haskell at Bump for various projects and we're both heavy users of the list comprehensions, first-class functions and other functional constructs that are available in Python. Scala let us express problems in a way we were used to.
  • Scala works very well with existing Java frameworks. Android is, of course, one big Java framework and we were going to have to interface with it a lot. A number of people asked, given the above, why not use Clojure--this is why.
  • An Android Service can withstand higher latency. Scala runs a little slower than Java (I've heard about 6x in benchmarks, but I'd bet it's worse in Dalvik), but this was something we could tolerate. If an application takes 50ms extra to render a cell in a list, the user will most certainly notice. If, however, the Service takes 50ms more process something it had to fetch from the network, nobody cares--it took 10x longer to do the network fetch anyway.

Why not Scala?

With all that out of the way, it's worth taking a minute to talk about some of the problems we ran into.

  • Scala does have public member variables. To support some of the syntactic changes that Scala makes, it replaces public member variables with accessor functions. In Scala, when you do something like foo.bar, it implicitly calls the function bar() (that returns the value of the private member variable bar) on foo. Java, of course, doesn't do this. So, when you are using Scala classes in Java code, everything becomes a function and you have to explicitly refer to foo.bar() everywhere. An easy problem to deal with, but it requires the programmer to remember whether something they are using is a Scala class or a Java one.
  • The above creates a more subtle problem with Android that I wanted to call out specifically--Parcelables. Android's Parcelable interface depends on being able to access the public member variable CREATOR on a class that implements Parcelable. If you create the class in Scala, then, of course, CREATOR ends up being a private member variable with a matching accessor function. There's no easy way around this problem, but thankfully Stéphane Micheloud committed a patch to the Scala trunk to solve this problem. This does mean if you're planning on using Parcelables, you're going to need to use a build of Scala that includes this patch.
  • Scala doesn't have an equivalent concept to public static final variables in interfaces (and honestly, it's a bit of a mystery to me why they exist in Java as well). This problem can easily be solved by creating a Java wrapper class that maps values from the interface to member variables on the class. For example,

import com.some.interface.SomeConsts;

class Consts {


      public static final CONST_A = SomeConsts.CONST_A;
      public static final CONST_B = SomeConsts.CONST_B;
      ...
}

  • To support anonymous functions and some of the other language constructs that Scala adds, it ends up creating a far larger number of classes than Java. Generally, this shouldn't be a problem, however, Android appears to have a limit on the number of classes that a single application can have. I don't have details on exactly what this limit is, but we did find that inheriting from the Scala classes pushed that number up a lot. At one point, we tried inheriting from the Map class and that pushed us over the edge. In general, inheritance can be rewritten as a standard class with the proposed parent class as a member variable, but it's certainly not as clean.

How Scala?

Before I get too deep into the specifics of how we did it, I want to point everyone to Stéphane Micheloud site on putting Scala on Android. Not only is this site a great resource, but Stéphane was immesurably helpful in getting us up and running.

Our build process consists of three steps, the first compiled the Google Protobufs that we use to communicate between our client and the server, the second invoked the Scala compiler to build the Service and finally we went back to the Java compiler to build the Application level code. I've attached the full versions of our build.xml and build-scala.xml (a modified version of the one on Stéphane's site), but I'll call out a few things here that might be of interest.

<property name="extensible.classpath" value="${scala-library.jar}" />

If you're accessing any Scala objects in Java, you're going to need to let the Java compiler know how those objects work. Unfortunately, there's no mechanism for extending properties in ant, so when we started working on a new feature that involved Google Maps, we had to change this to:

<property name="extensible.classpath" value="${scala-library.jar};${path.to.maps.jar}" />

<target name="-service-pre-compile"


        description="Compiled the protocol buffers"
        depends="-aidl, -resource-src">
  <javac encoding="ascii" target="1.5" debug="true" extdirs=""
         includes="src/com/google/**,src/com/bump/proto/**"
         destdir="${out.classes.absolute.dir}"
         bootclasspathref="android.target.classpath"
         verbose="${verbose}">
    <src path="." />
    <classpath>
      <fileset dir="${jar.libs.absolute.dir}" includes="*.jar" />
    </classpath>
  </javac>
</target>

This is our compile step for protocol buffers. It looks just like the version in the Android SDK, except we've given it a new name and restricted the files it's compiling with the includes statement.

<target name="scala-compile" depends="-service-pre-compile"
    description="Compiles project's .scala files into .class files"
    if="myapp.containsScala" unless="do.not.compile">
    <condition property="logging" value="verbose" else="none">
        <istrue value="${verbose}" />
    </condition>
    <property prefix="scala"
        resource="compiler.properties"
        classpathref="scala.path" />
    <echo
        message="Scala version ${scala.version.number} - http://scala-lang.org"
        level="info" taskname="fsc" />
    <fsc
        srcdir="." includes="gen/**,src/com/bump/core/**,src/com/bump/util/*.java,src/com/bump/*.java"
        destdir="${out.classes.dir}"
        bootclasspathref="android.target.classpath"
        deprecation="yes"
        logging="${logging}" addparams="${scalac.addparams}">
        <classpath>
            <pathelement location="${scala-library.jar}" />
            <pathelement location="${out.classes.dir}" />
            <fileset dir="${jar.libs.absolute.dir}" includes="*.jar" />
        </classpath>
    </fsc>
    <touch file="${out.dir}/classes.complete" verbose="no"/>
</target>

The is the step to compile the scala code (from build-scala.xml). One thing we changed from Stéphane's version is we're using fsc in instead of scalac. fsc (Fast Scala Compiler) acts just like the regular Scala compiler, but it's faster. It does, however, do some caching to speed things up, so if you're trying to do a clean build, you need to tell fsc (fsc -reset).

Jamie uses vim and I use emacs, and both of just like the command line too much to use Eclipse, so this is where I'm going to have to stop. Since I know many of you use Eclipse, I'll call out Indy and Jake to talk about how they handled the Scala code in Eclipse.

Want to work with Will and the rest of the Bump team? We are hiring: http://bu.mp/jobs.