Developing for Android
At the time of writing, the following facts hold true:
- Android applications are self-contained, there appears to be no way for users to deploy a shared library to a device
- The scala library therefore needs to be embedded in every android application that uses it
- The Scala nature can be successfully added to an ADT project
- Using ProGuard is *highly* desirable, to keep these apps to a manageable size
- There is no usable1 eclipse builder for proguard that we can add to a hybrid Scala/ADT project
- Using the Android SDK to create an ant-based project from the command line yields the exact same project layout as using the eclipse plugin
1 Obfuscate4e and a couple of JavaME toolkits add ProGuard support, but not in a way that's suitable for our needs.
For the rest of this article, I'll be assuming that:
- your environment is fully set up
- you have a configured Android Virtual Device targeting SDK 7 (Android 2.1)
- you've been able to deploy a Java-based application to it
- You're using Scala 2.8 and the matching IDE plugin
As Proguard can't be embedded into the Eclipse build process, we'll create an Ant build instead and have Eclipse use that as an "External Task".
Step 1: Create the ant files for your project:
cd <project dir>
android update project --target 1 --path .
--target 1 specifies the Virtual Device to use. If you have more than one then they can be listed with:
android list targets
This will create the three files: build.properties, default.properties and build.xml
Step 2: Customise your ant file
replace the line
<setup />
With this code.
NOTE: On windows change the ":" to a ";" in the line "-injars ${out.classes.absolute.dir};tools/scala-library.jar(!META-INF/MANIFEST.MF,!library.properties)" if you get errors like this: "Can't read [proguard.ClassPathEntry@146e381] (No such file or directory)".
As explained in build.xml, this code is copied from <SDK>/platforms/<target_platform>/templates/android_rules.xml with the following modifications:
- macro "dex-helper" updated to use classes.min.jar (instead of /classes) as the input
- target "compile" has a scalac task added at the end
- added new target "proguard", depending on "compile" that generates classes.min.jar from /classes
- target "-dex" now depends on proguard instead of compile
You'll also need a /tools directory in the root of your project containing:
- proguard.jar
- retrace.jar (from the ProGuard download)
- scala-compiler.jar
- scala-library.jar
NOTE: With version 7 of the Android SDK tools, the apkbuilder ant task has been updated so the default build.xml no longer works; see http://www.mail-archive.com/android-developers@googlegroups.com/msg117046.html. I had to replace the apkbuilder section in the above link with this:
<apkbuilder outfolder="${out.absolute.dir}" resourcefile="${ant.project.name}.ap_" apkfilepath="${out.debug.unaligned.package}" debug="${build.debug}" abifilter="${filter.abi}" verbose="${verbose}" hascode="true"> <dex path="${intermediate.dex.file}"/> <sourcefolder path="${source.absolute.dir}"/> <sourcefolder refid="android.libraries.src"/> <jarfolder path="${external.libs.absolute.dir}" /> <jarfolder refid="android.libraries.libs" /> <nativefolder path="${native.libs.absolute.dir}" /> <nativefolder refid="android.libraries.libs" /> <extra-jars/> </apkbuilder>
Step 2a: Test
Before deploying to your virtual machine, it must first be running, you have two options here:
a. via the "SDK and AVD Manager", (run with the command `android`) select and start the virtual device
b. If you know the device name (mine is "Nexus.1"), then you can directly use the command: emulator -avd Nexus.1
Once your emulator is running you can just leave it there, the boot time is too slow to restart the thing for every test!
You can now deploy the application with
ant install
( may need to increase to increase memory for ant, 'export ANT_OPTS=-Xmx1024m' )
This won't automatically launch it as the Eclipse plugin does, but the application WILL now be installed and usable on your virtual device.
If working move to Step 3
If you have more than one device running (maybe emulator and physical phone connected) the you will need to copy the app by hand. To list devices:
adb devices
then copy app to device
adb -s emulator-5554 install -r ./Hello.apk
- -s <device> device to be installed on
- -r write over previous version
If this all works, proceed to the next step...
Step 3: Use some Scala code!
As normal for any other pre-existing Java project, you first switch to the Scala perspective, then add the Scala nature (via the Configure... menu on right-clicking the project)
This will also add the JDK libraries to your classpath. These aren't needed for Android development and should be removed, leave the Scala libraries on the classpath though.
Replace your java Activity class with its Scala equivalent. This is what the default Activity.java looks like when rewritten as Activity.scala:
package com.example.helloandroid
import android.app.Activityimport android.os.Bundle
class HelloAndroid extends Activity {
override def onCreate(savedInstanceState:Bundle) : Unit = {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
}
}
Install it again with `ant install`, you're now running Scala 2.8 on Android!
Step 4: Create an External Tool configuration in Eclipse to launch the Ant Target
Open the External Tools Configurations in Eclipse and create a new Ant Build. Define following settings:
- Buildfile: ${project_loc}\build.xml
- Base Directory: ${project_loc}
- In the tab "Targets" choose the target "install"
- Open the tab JRE and add the VM arguments -Xmx1024m
Running this external tool will start the Ant target install and run's the application on your Android emulator.
Comments are disabled for this space. In order to enable comments, Messages tool must be added to project.
You can add Messages tool from Tools section on the Admin tab.