Scala on your phone

Create mobile applications using Android, Scala, and Eclipse

The Android operating system provides a powerful, open platform for mobile development. It leverages the power of the Java™ programming language and the Eclipse tools platform. Now you can add the Scala programming language to that mix. In this article, see how you can use Scala as the primary development language on Android, allowing you to write mobile applications using a more-expressive, but also more type-safe, programming language.

Share:

Michael Galpin, Software architect, eBay

Michael_GalpinMichael Galpin is an architect at eBay and is a frequent contributor to developerWorks. He has spoken at various technical conferences, including JavaOne, EclipseCon and AjaxWorld. To get a preview of what he is working on, follow @michaelg on Twitter.



30 June 2009

Also available in Japanese

Prerequisites

In this article, we will create a mobile application that will run on any Android device. You will need to install the Android SDK; Android V1.5 SDK was used here. The application code will be written in the Scala programming language. If you have never seen Scala before, that is OK because the Scala code will be explained. However, it is recommended that you are at least familiar with the Java language if you are not familiar with Scala. Scala V2.7.5 was used to develop the code in this article. For Android and Scala, there are excellent Eclipse plug-ins available. Eclipse V3.4.2 was used, along with Android Development Tools (ADT) V0.9.1 and V2.7.5 of the Scala IDE plug-in. See Resources for all of these tools.


Setup

Writing an Android application may sound like a tricky proposition. Android applications run inside their own virtual machine: the Dalvik virtual machine. However, the build path for an Android application opens things up for us. The basic strategy we will use is illustrated below.

Figure 1. Build path for Scala on Android
Build path for Scala on Android

The idea is that we will first compile all of the Scala code to Java class files. This is what the Scala compiler does, so there is nothing too tricky about this. Next, we take the Java class files and use the Android dex compiler to compile the class files to the format used by the Dalvik VM on an Android device. This is known as dexing and is the normal compile path for an Android application. Usually, you go from .java files to .class files to a single .dex file. The only thing different in our case is that we start with .scala files. Finally, the .dex file and other application resources are zipped up as an APK file that can be installed on an Android device.

So how do we make all of this happen? We will use Eclipse to do most of the heavy lifting for us. However, there is one tricky step: For our code to run, it also needs code from the standard Scala library. In a typical Scala installation, this is a single JAR found in /lib/scala-library.jar. This JAR, however, includes certain code not supported on Android. Some code needs to be tweaked slightly, and some code must be removed. A custom build of scala-library.jar works best, at least for now. See Resources for the custom build used here. We will refer to this JAR as the Android library JAR.

Once we have that JAR, the rest is pretty easy. Just create an Android project using the ADT plug-in for Eclipse. Then add a Scala nature to the project. Replace the standard Scala library with the Android library talked about above. Finally, add the output directory to your classpath. Now you are ready to go. This is described in more detail in a note from the main Scala site (see Resources). Now that we have the basic setup, let's take a look at the Android application we will create using Scala.


UnitsConverter

Now that we know how to take Scala code and turn it into the binary format that will run on an Android device, it's time to create a mobile application using Scala. The application we will create will be a simple unit-converter application. This will let users easily convert from English to metric units and vice-versa. This is a pretty simple application, but we will see how even the simplest applications can benefit from using Scala. Let's start out by looking at the layout elements of UnitsConverter.

Creating the layout

You might be excited to write Scala that runs on your phone, but not all mobile development coding should be done in Scala, or the Java language, for that matter. The Android SDK provides a nice way to separate the user-interface code from application logic using an XML-based layout system. Let's look at the main layout file for our application, shown in Listing 1.

Listing 1. Main layout for the Converter application
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:gravity="center_horizontal" android:padding="10px"
    >
    <TextView android:id="@+id/prompt_label" android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:text="@string/prompt_metric"/>
    <EditText android:id="@+id/amount" android:layout_below="@id/prompt_label"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"/>
    <TextView android:id="@+id/uom_label"  
        android:layout_below="@id/amount"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:text="@string/uom"/>
    <Spinner android:id="@+id/uom_value"
        android:layout_below="@id/uom_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button android:id="@+id/convert_button"
        android:layout_below="@id/uom_value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/convert_button_label"/>
    <TextView android:id="@+id/result_value"
        android:layout_below="@id/convert_button"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>        
</RelativeLayout>

The above code very succinctly creates the main UI for the application. Its root node is a RelativeLayout container element. There are many layout options available in the Android SDK. A RelativeLayout simply instructs the runtime to lay out various UI widgets using relative positioning. To use relative positioning, we add a visible element — in this case, a TextView element. This is a simple element for displaying text. It is assigned an ID of prompt_label. This is used by the next element, an EditText element (a text input box). This element has a layout_below attribute for which the value is equal to the prompt_label ID. In other words, EditText should be placed below the element called prompt_label.

The rest of the layout code is very straightforward. All together, there is a text input box with a label, a spinner (a combo box or a drop-down) with a label, a button, and a another text area for output. Figure 2 shows a picture of the running application, with elements identified.

Figure 2. An Android lLayout — dissected
An Android lLayout -- dissected

So where do the various text values seen in the above view come from? Notice that several of the elements in Listing 1 have a text attribute. For example, the prompt_label element has a text attribute equal to @string/prompt_metric. That indicates it is using one of the standard resource files in an Android application: the strings.xml file, shown in Listing 2.

Listing 2. The strings.xml resource
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="prompt_metric">Enter amount (KM, g, L, C)</string>
    <string name="prompt_english">Enter amount (miles, lbs, gallons, 
F)</string>
    <string name="uom">Units of Measure</string>
    <string name="convert_button_label">Convert</string>
    <string name="app_name">Converter</string>
    <string name="english_units">English</string>
    <string name="metric_units">Metric</string>
</resources>

Now you can see where all of the text in Figure 2 is coming from. The spinner has a drop-down of possible units of measure to use, and those units are not listed in Listing 2. Instead, they come from another file, arrays.xml, shown in Listing 3.

Listing 3. The arrays.xml resource
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="english_units">
        <item>Fahrenheit</item>
        <item>Pounds</item>
        <item>Ounces</item>
        <item>Fluid Ounces</item>
        <item>Gallons</item>
        <item>Miles</item>
        <item>Inches</item>
    </array>
    <array name="metric_units">
        <item>Celsius</item>
        <item>Kilograms</item>
        <item>Grams</item>
        <item>Millileters</item>
        <item>Liters</item>
        <item>Kilometers</item>
        <item>Centimeters</item>
    </array>    
</resources>

Now we can see the values that will be used for the spinner. How do these actually wind up in the spinner, and how can the application toggle between English and metric units? To answer those questions, we have to take a look at the application code itself.


The Scala application code

The application code for the Converter application is pretty simple — in any language. It could, of course, be done relatively easily in the Java language, but it is certainly no more complex to do it in Scala. In fact, as we will see, many things are made much simpler by using Scala. Let's start by looking at the code behind the UI we have been examining.

The code behind the view

The easiest way to explain the Scala code that helps create the UI is to take a look at it and go through it. For any application, you define the default activity of your application in the application's AndroidManifest.xml file. Any UI is backed up by an Activity class, and the default Activity defines the Activity class executed when the application is initially loaded. For an application as simple as this one, this is the only activity needed. For this application, a class called Converter is listed, and its source code is shown in Listing 4.

Listing 4. The Converter activity class
class Converter extends Activity{
    import ConverterHelper._
    private[this] var amountValue:EditText = null
    private[this] var uom:Spinner= null
    private[this] var convertButton:Button = null
    private[this] var resultValue:TextView = null
    
    override def onCreate(savedInstanceState:Bundle){
      super.onCreate(savedInstanceState)
      setContentView(R.layout.main)
      uom = findViewById(R.id.uom_value).asInstanceOf[Spinner]
      this.setUomChoice(ENGLISH)
      amountValue = findViewById(R.id.amount).asInstanceOf[EditText]
      convertButton = findViewById(R.id.convert_button).asInstanceOf[Button]
      resultValue = findViewById(R.id.result_value).asInstanceOf[TextView]
      convertButton.setOnClickListener( () => {
          val unit = uom.getSelectedItem.asInstanceOf[String]
          val amount = parseDouble(amountValue.getText.toString)
          val result = UnitsConverter.convert(Measurement(unit,amount))
          resultValue.setText(result)
      })
    }
    override def onCreateOptionsMenu(menu:Menu) = {
      super.onCreateOptionsMenu(menu)
      menu.add(NONE, 0, 0, R.string.english_units)
      menu.add(NONE, 1, 1, R.string.metric_units)
      true
    }
    override def onMenuItemSelected(featureId:Int, item:MenuItem) = {
      super.onMenuItemSelected(featureId, item)
      setUomChoice(if (item.getItemId == 1) METRIC else ENGLISH)
      true
    }
    private 
    def setUomChoice(unitOfMeasure:UnitsSystem){
      if (uom == null){
        uom = findViewById(R.id.uom_value).asInstanceOf[Spinner]
      }
      val arrayId = unitOfMeasure match {
        case METRIC => R.array.metric_units
        case _ => R.array.english_units
      }
      val units = new ArrayAdapter[String](this, R.layout.spinner_view, 
        getResources.getStringArray(arrayId))
      uom.setAdapter(units)      
    }
}

Let's start at the top of this class. It extends android.app.Activity. This is a Java class, but you can easily subclass Java classes from Scala. Next, it has several instance variables. Each of these corresponds to a UI element defined earlier. Notice that each is also scoped as private[this]. This demonstrates a level of access control available in Scala that does not exist in the Java language. Not only are the variables private but they are private to the particular instance of the Converter class. This level of access control might be overkill for a mobile application, but if you happen to be a Scala developer, it is reassuring that all of the syntax you are accustomed to is still available on an Android application.

Getting back to the code in Listing 4, notice that we override the onCreate method. This is a method defined in the Activity class and is typically overridden by any custom Activity. If you were writing this code in the Java language, you should add an @Override annotation. In Scala, override is a keyword, required to help ensure correctness. This would prevent a common mistake like misspelling the method name. If you misspelled it, the Scala compiler would catch this and give you an error. Notice that on this method, as well as all of the others, you do not need to declare a return type. The Scala compiler is easily able to infer this information, so there's no need to be redundant.

Most of the code in onCreate is similar to what you would do in the Java language. There are a couple of things of interest. Notice that we use the method findViewById (defined in the superclass Activity) to get a handle on various UI elements. This method is not type-safe and requires a cast. To typecast in Scala, use the parameterized method asInstanceOf[T], where T is the type you are casting to. The cast is functionally just like it would be in the Java language; Scala just has nicer syntax for it. Next, notice the call to setUomChoice (we will go into detail on this method shortly). Finally, notice that we get a handle on the button we created in the layout XML and add a click event handler.

If this was written in the Java language, we would have to pass in an implementation of the Android interface OnClickListener. This interface defines a single method: onClick. Really, all you care about is that method, but there is no way to pass in a method directly in the Java language. This is not the case in Scala, where we are able to pass in a method literal, or closure. Here, we are denoting a closure by using the syntax () => { ... }, where the method body is the contents of the curly braces. The open/close parentheses denote a function that takes no parameters. However, we are passing this closure to the setOnClickListener method on an instance of Button, a Java class defined in the Android SDK. How can we pass a Scala closure to a Java API? Let's take a look.


Functional programming on Android

To understand how we get Android APIs to work with function literals, look at the first line of the Converter class definition. It is an import statement. This is another nice feature of Scala. You can import packages, classes, etc. anywhere in the code, and they are scoped to where you import them. In this case, we are importing everything from something called ConverterHelper. The code for ConverterHelper is shown in Listing 5.

Listing 5. The ConverterHelper
object ConverterHelper{
  import android.view.View.OnClickListener
  implicit def funcToClicker(f:View => Unit):OnClickListener = 
    new OnClickListener(){ def onClick(v:View)=f.apply(v)}
  implicit def funcToClicker0(f:() => Unit):OnClickListener = 
    new OnClickListener() { def onClick(v:View)=f.apply}
}

This is a Scala singleton because it uses the object declaration instead of a class declaration. The singleton pattern is baked directly into Scala and is used anywhere you would use static methods or variables in the Java language. In this case, the singleton simply holds a pair of functions: funcToClicker and funcToClicker0. These take a function as an input parameter and return an instance of OnClickListener, the interface defined in the Android SDK. For example, funcToClicker is defined as taking a function f. The function f is type as a function that takes a single input parameter of type View (another class from Android) and returns Unit, which is the Scala equivalent of void. It then returns an implementation of OnClickListener, where that interface's onClick method is implemented by simply applying the input function f to the View parameter. The other function, funcToClick0, does the same thing, but takes a function that has no input parameter.

Both of these functions (funcToClicker and funcToClicker0) are defined as implicit. This a convenient feature of Scala. It allows types to be implicitly converted to another type by the compiler. In this case, when the compiler parses the Converter class's onCreate method, it encounters a call to setOnClickListener. This is a method that requires an instance of OnClickListener. However, the compiler finds a function, instead. Before it complains and compilation fails, the compiler checks to see if there are any implicit functions in scope that would allow it to convert the function to an OnClickListener. Indeed, there is, so it performs this conversion, and all is well. Now that we understand how to use closures within Android, let's take a look at more of the application logic — in particular, how the unit-conversion calculations are performed.

Unit conversions and calculations

Let's go back to Listing 4. The function passed in to onClickListener retrieves the units of measurement and the value entered by the user. It then creates a Measurement instance and passes this to an object called UnitsConverter. The code for these entities is shown in Listing 6.

Listing 6. Measurement and UnitsConverter
case class Measurement(uom:String, amount:Double)

object UnitsConverter{
      // constants
    val lbToKg = 0.45359237D
      val ozToG = 28.3495231
      val fOzToMl = 29.5735296
      val galToL = 3.78541178
      val milesToKm = 1.609344
      val inchToCm = 2.54  
   
      def convert (measure:Measurement)= measure.uom match {
          case "Fahrenheit" => (5.0/9.0)*(measure.amount - 32.0) + " C"
            case "Pounds" => lbToKg*measure.amount + " kg"
            case "Ounces" => ozToG*measure.amount + " g"
            case "Fluid Ounces" => fOzToMl*measure.amount + " mL"
            case "Gallons" => galToL*measure.amount + " L"
            case "Miles" => milesToKm*measure.amount + " km"
            case "Inches" => inchToCm*measure.amount + " cm"
            case "Celsius" => (9.0/5.0*measure.amount + 32.0) + " F"
            case "Kilograms" => measure.amount/lbToKg + " lbs"
            case "Grams" => measure.amount/ozToG + " oz"
            case "Millileters" => measure.amount/fOzToMl + " fl. oz."
            case "Liters" => measure.amount/galToL + " gallons"
            case "Kilometers" => measure.amount/milesToKm + " miles"
            case "Centimeters" => measure.amount/inchToCm + " inches"
            case _ => ""
      }
}

Measurement is a case class. This is a convenience feature of Scala. Decorating a class with "case" causes it to have a constructor generated that requires the attributes of the class, as well as implementations of equals, hashCode, and toString. It is perfect for data structure classes, like Measurement. It also generates getters for the attributes defined — in this case, uom and amount. We could have defined those attributes as vars (mutable variables), then setters would have also been generated for us. That single line of Scala code does a lot!

Next, UnitsConverter is also a singleton as it is defined using the object keyword. Its single method is convert. Notice how convert is defined as being equal to a single statement — a match statement. It is a single expression, so no extra curly braces are needed. It uses Scala's pattern matching. This is a powerful feature common in functional programming languages. It is similar to a switch statement in the Java language and many other languages. However, we are able to match against strings (actually, the matching can be much more sophisticated than this.) The string is matched, the appropriate calculation is performed, and a formatted string is returned to be displayed. Finally, notice the last case that matches _. The underscore is used as a wildcard in many places in Scala. In this case, it says match anything, kind of like a default statement in the Java language.

Now that we understand the calculations in the application, let's finish off the application by looking at the rest of the UI setup and menus.

UI initialization and menus

Let's go back to Listing 4. We promised to look at the setUomChoice. This method is defined as taking a parameter of type UnitsSystem. Let's take a look at how this type is defined.

Listing 7. The UnitsSystem
sealed case class UnitsSystem()
case object ENGLISH extends UnitsSystem
case object METRIC extends UnitsSystem

We see that UnitsSystem is a sealed case class with no attributes. That doesn't seem very useful. Next, we see two case objects. Remember that object denotes a singleton in Scala. In this case, there are two case objects and each extend UnitsSystem. This is a common idiom in Scala to provide a simpler, more type-safe way of doing enumerations.

Now the implementation of setUomChoice makes more sense. After we get a handle on the spinner, we match against what type of UnitsSystem was passed in. This identifies an array to use from the arrays.xml we saw earlier. This is using the R class that the Android SDK generates for us to represent resources, such as the arrays.xml file. Once we know which array to use, we use that array as the data source of the spinner by creating an adapter (in this case, an ArrayAdapter) that we pass in to the spinner.

Finally, look at the onCreateOptionsMenu and onMenuItemSelected methods from Listing 4. These are methods defined in Activity we are overriding in our Converter activity. The first method creates a menu. The second handles the event of a user selecting either English or metric from the menu. It simply calls the setUomChoice again. This allows the user to toggle between converting from English to metric units, or from metric to English units.


Summary

The architecture of the Android platform opens it up to any programming language that runs on the Java Virtual Machine. We have seen how to set up an Android project to work with Scala code. This type of procedure can be extended to other JVM programming languages, as well, like Groovy, JRuby, or Fan. With the Scala programming language at our disposal, it becomes even easier to write Android applications. You are still able to develop using Eclipse. Debugging both with the emulator and a device work straight from Eclipse, as well. You get all of the tools and a more productive programming language.


Download

DescriptionNameSize
Converter sampleos-eclipse-scala-Converter.zip2KB

Resources

Learn

Get products and technologies

Discuss

  • The Eclipse Platform newsgroups should be your first stop to discuss questions regarding Eclipse. (Selecting this will launch your default Usenet news reader application and open eclipse.platform.)
  • The Eclipse newsgroups has many resources for people interested in using and extending Eclipse.
  • Participate in developerWorks blogs and get involved in the developerWorks community.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Open source on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source
ArticleID=398968
ArticleTitle=Scala on your phone
publish-date=06302009