August 13th, 2013

Spiketail Hatchling

Android Development sans Eclipse

When I started mobile development just over a year ago, iOS stuff was simple. There were iPhone and iPad apps and they were made in Xcode. At first, I had no idea where to go with Android and ended up generating a simple twelve-step procedure to get a sample app onto a device. Then, I discovered the ADT for Eclipse and that was that. That's the tools that all the developers are using. I became a pretty big fan. Eclipse is a really nifty tool with lots of good integration points with Android-- including some REALLY flashy memory and time profiling toys.

And then I'd use EMACS for everything else.

If you organize your project correctly (and don't mind doing edit-build-test cycles), one can easily cut out the eclipse piece from this equation.

Here are the rules (paths relative to a project's home directory):
  1. Source files in src/com/package/name
  2. Layout files in res/layout
  3. String values in res/values
  4. AndroidManifest.xml and goes in /
  5. dex files get generated into /build (so, remember to mkdir build)
  6. Copy requisite libraries to be somewhere that you'll remember.
  7. Always use a build script!

A build script-- is something easily generated. It does require a few steps, described in English here:

  1. aapt p -vfm -S res/ -J src/ -M AndroidManifest.xml -I /.../android-sdk/platforms/android-16/android.jar — We build the file used in the source code to pull things from XML into Java.
  2. javac -classpath /.../android-sdk/platforms/android-16/android.jar:(other JARs here) src/org/package/name/* -d bin/ — Let's actually compile the .java files.
  3. dx --dex --output=build/classes.dex bin (other JARs' w/complete paths here) — Generate a .dex which is Android bytecode of your Java and XML goodies.
  4. aapt p -vf -M AndroidManifest.xml -S res/ -I /.../android-sdk/platforms/android-16/android.jar -F unsigned.apk build/ — Build the original, unsigned APK. This will need to be "signed" before it can run on a device...
  5. keytool -genkeypair -validity 10000 -dname "CN=company name" -keystore appname.keystore -keyalg RSA -alias someAlias — This doesn't need to be in your, but it does need to be run once per app to generate the .keystore file that signs the APK. The validity argument is in days-- for how long does your APK stay valid? You'll be prompted for a password. Make it obvious to yourself.
  6. jarsigner -verbose -keystore appname.keystore -signedjar signed.apk unsigned.apk someAlias — Crytograhically signs the APK, locking all its goodies inside in a basic attempt to prevent reverse engineering.

Then, to run the app programatically, here are these steps (for use with an emulator, replace -d with -e):
  1. adb -d uninstall — Uninstall existing app.
  2. adb -d install signed.apk — Install the new app
  3. adb shell am start -n — Launch the activity.

I'd recommend putting those in the same build script. Emacs has a pretty nice compile mode, so I have this in my .emacs file:

(global-set-key (kbd "") 'compile) I can press F5 and run the build script.

Here's an example build script that uses Millennial Media's SDK as an external library (it's a stress test called 'CornerSim')...

mkdir build
aapt p -vfm -S res/ -J src/ -M AndroidManifest.xml -I ~/android-sdk/platforms/android-16/android.jar
javac -classpath /Users/mburger/android-sdk/platforms/android-16/android.jar:/Users/mburger/Downloads/MM-android-5.0.1/MMSDK.jar src/org/awesome/stress501/* -d bin/
dx --dex --output=build/classes.dex bin /Users/mburger/Downloads/MM-android-5.0.1/MMSDK.jar 
aapt p -vf -S res/ -M AndroidManifest.xml -I ~/android-sdk/platforms/android-16/android.jar -F unsigned.apk build/
jarsigner -verbose -keystore cornersim.keystore -signedjar signed.apk unsigned.apk cornersim
adb -d uninstall org.awesome.stress501
adb -d install signed.apk
adb shell am start -n org.awesome.stress501/org.awesome.stress501.Banner

...and that's that, friends. While I wrote this with EMACS in mind, it should free you up for vi, SAM, notepad, or even ed if you're so inclined.