Posted by admin on Mar 22, 2012 in
Uncategorized
I am working on an Android project constructed of:
- The main app (very lightweight wrapper + AndroidManifest.xml)
- The main library (where all the real work gets done)
- Facebook-android-sdk
- HockeySDK-Android
Recently, I started seeing the following error when building the app using ant:
[dx] UNEXPECTED TOP-LEVEL EXCEPTION:
[dx] java.lang.IllegalArgumentException: already added: Lcom/facebook/android/R$anim;
[dx] at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
[dx] at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
[dx] at com.android.dx.command.dexer.Main.processClass(Main.java:486)
[dx] at com.android.dx.command.dexer.Main.processFileBytes(Main.java:455)
[dx] at com.android.dx.command.dexer.Main.access$400(Main.java:67)
[dx] at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:394)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:245)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:131)
[dx] at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
[dx] at com.android.dx.command.dexer.Main.processOne(Main.java:418)
[dx] at com.android.dx.command.dexer.Main.processAllFiles(Main.java:329)
[dx] at com.android.dx.command.dexer.Main.run(Main.java:206)
[dx] at com.android.dx.command.dexer.Main.main(Main.java:174)
[dx] at com.android.dx.command.Main.main(Main.java:95)
[dx] 1 error; aborting
Upon inspection, it appeared that there were multiple R.java files per module with different package names but the same content. Removing all the “gen” directories in the entire project resulted in a successful from the command line.
Posted by admin on Aug 26, 2011 in
Android
Why build an Android App from the command line?
For the purpose of creating a continuous integration build of an Android app, I needed to be able to build the app and its dependent modules from the command line. This is done using ant.
Prerequisites
Of course, you must have the appropriate Android SDK installed for your development platform. Make sure the tools directory of the Android SDK is in your PATH.
You’ll also want to install ant.
If you don’t already have Java installed, then maybe you should go visit the Android Developer site for some important background information.
Your Project
If you created your project using IntelliJ, then the build files mentioned below should be created for you automatically. If you created your project using Eclipse, then you’ll have to take an extra step to create the build files. Simply cd into the root directory of your project and execute the android command to generate the build files:
$ cd android-project-directory
$ android update project --path .
This creates build.xml, default.properties, and local.properties for your project.
Important Files
There are four build files of critical importance which you can find in the root directory of your project:
build.xml — this is the main ant build script. Check this file into your version control system.
default.properties — has a huge warning that says it’s generated by the Android tools and should not be modified. Check this file into your version control system.
ant.properties (optional) — allows you to add application-build-specific entries used by the build script. Typically empty for a straightforward Android app build but can be customized for non-standard directory structure or build dependencies. Check this file into your version control system or omit it entirely from the project if you have no customizations or build dependencies.
local.properties — also generated by Android tools but should not be checked into your version control system. This is where the local path to your Android SDK directory root is specified, and this typically varies from one machine or build environment to the next.
Build Command
In order to build the app from the command line, cd to the root directory of your Android project (where the above files live and typically also where your src directory and your AndroidManifest.xml file live) and execute the ant command:
$ cd android-project-directory
$ ant clean debug
This command removes any leftover binaries or other artifacts from a previous build and rebuilds the app from scratch. If that is successful, then it packages and signs a debug version of the app. The console output from the command tells you where you can find the resulting .apk file for the app. Here’s an example of the console output from a successful build showing the location of the resulting .apk file:
$ ant clean debug
Buildfile: /Users/mharper/Development/Android/Demo/HelloCI/build.xml
[setup] Android SDK Tools Revision 10
[setup] Project Target: Android 2.2
[setup] API level: 8
[setup]
[setup] ------------------
[setup] Resolving library dependencies:
[setup] No library dependencies.
[setup]
[setup] ------------------
[setup]
[setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.
[setup]
[setup] Importing rules file: tools/ant/main_rules.xml
clean:
[delete] Deleting directory /Users/mharper/Development/Android/Demo/HelloCI/bin
[delete] Deleting directory /Users/mharper/Development/Android/Demo/HelloCI/gen
...
compile:
[javac] Compiling 2 source files to /Users/mharper/Development/Android/Demo/HelloCI/bin/classes
...
debug:
[echo] Running zip align on final apk...
[echo] Debug Package: /Users/mharper/Development/Android/Demo/HelloCI/bin/HelloCI-debug.apk
BUILD SUCCESSFUL
Total time: 4 seconds
Building an App with Dependencies
It is common for an app to depend on one or more libraries that are built with a separate project. Thankfully, the Android build files make this easy to deal with.
Let’s say my HelloCI app depends on a HelloCILib that is a separate project built as an Android library. Let’s also say that the HelloCI and HelloCILib root directories are in the same directory:
$ ls
HelloCI HelloCILib
In order for the HelloCILib to be built before HelloCI, all you have to do is to reference its root directory path in the build.properties file of the main project (HelloCI, in this case) thusly:
android.library.reference.1=../HelloCILib
You can add more dependent projects simply by bumping the number at the end of the property, e. g. android.library.reference.2 etc. I understand that you should not leave any gaps in the numbering, however.
Notice how the build looks slightly different now that the dependent library is included:
$ ant clean debug
Buildfile: /Users/mharper/Development/Android/Demo/HelloCI/build.xml
[setup] Android SDK Tools Revision 10
[setup] Project Target: Android 2.2
[setup] API level: 8
[setup]
[setup] ------------------
[setup] Resolving library dependencies:
[setup] /Users/mharper/Development/Android/Demo/HelloCI: ../HelloCILib => /Users/mharper/Development/Android/Demo/HelloCILib
[setup] ------------------
[setup] Ordered libraries:
[setup] /Users/mharper/Development/Android/Demo/HelloCILib
[setup] ------------------
[setup]
[setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.
[setup]
[setup] Importing rules file: tools/ant/main_rules.xml
clean:
[delete] Deleting directory /Users/mharper/Development/Android/Demo/HelloCI/bin
[delete] Deleting directory /Users/mharper/Development/Android/Demo/HelloCI/gen
...
compile:
[javac] Compiling 4 source files to /Users/mharper/Development/Android/Demo/HelloCI/bin/classes
...
debug:
[echo] Running zip align on final apk...
[echo] Debug Package: /Users/mharper/Development/Android/Demo/HelloCI/bin/com.standalonecode.HelloCI-debug.apk
BUILD SUCCESSFUL
Total time: 4 seconds
Summary
Building an Android app from the command line is very straightforward, especially if you have a standard Android app directory structure. All of this work is leading up to creating a continuous integration build under Jenkins at cloudbees.com which is the subject of another blog post.
The source for this example can be found on GitHub.
Posted by admin on Jul 12, 2011 in
Uncategorized
When I was working on ResEdit for Apple back in the mid-90s, I made a mathematical mistake that caused resizing to be geometric instead of linear. Man, you could resize a control very quickly that way! Anyway, today’s mathematical mistake wasn’t quite as serious, but still brought me a good chuckle.

Maybe I should make the circle fit *inside* the rectangle
Posted by admin on Apr 13, 2011 in
Android
I wasted a good amount of time this morning due to the Android Emulator’s inability to be moved from one network to another.
Because it takes so damn long to startup, I typically keep the Android Emulator running when I am working on Circle 8 for Android (as I have been lately). In a typical day, I encounter at least three wifi networks: home, office, and the coffee shop.
Apparently, the Emulator prefers a monogamous relationship with networks and thus doesn’t switch over to a new wifi connection. I was trying to setup the Email app in the Emulator to connect to my email account and it failed over and over again. I finally decided to restart the Emulator, thinking that maybe it was lost with respect to the network. Sure enough, restarting the Emulator resulted in being able to browse to a web page as well as setup the Email app no problem.
Edit (August 2011):
I have since abandoned the Emulator in favor of developing directly to an Android device. Significantly snappier and less prone to bizarre errors.
Posted by admin on Jan 19, 2011 in
Ajax,
Cucumber,
Rails,
Testing
On my current Rails project, I have been working on constraining “check-ins” to once daily or once weekly. From a Cucumber scenario perspective, this means using Timecop to travel to a specific time/date, popping a jQuery dialog, entering some data, and pressing the Submit button. This procedure is then immediately repeated, traveling to a different point in time. Upon completion of the successful path, I was asserting that both “check-ins” took place by looking at the model/database. Unfortunately, this would fail quite randomly. It was as if the second time travel was taking place before the first check-in was being written to the database. If so, this would cause the second check-in to fail the daily or weekly constraint during validation.
What I needed to do was WAIT — wait for the check-in dialog to close before the second time travel.
It took some poking around, but I finally settled on the following step definition:
When /^I wait for (.*)to finish$/ do |sugar|
page.wait_until do
done = page.evaluate_script("window.jQuery.active == 0")
putc done ? '*' : '+'
done
end
end
This allows me to write a step such as:
And I wait for the check-in to finish
This step prints a + every time through the loop while the page is still active, and then a * when it’s done. (Obviously, this is window dressing and not integral to the success of the step.) Not only did this fix the scenario failures I had due to the race condition, it also got rid of the random “connection reset” errors I was seeing.
Posted by admin on Sep 2, 2010 in
iPod / iPhone
In an iPhone app I’m working on which uses an MKOverlayView subclass, I found that the lines I was drawing were thinner on iPhone 4 than on iPhone. Simple math to the rescue so the line has the same thickness on both platforms (e. g. I want a uniform lineWidth of 3.0):
overlayView.lineWidth = 3.0 * [[UIScreen mainScreen] scale];
Posted by admin on Jul 15, 2010 in
Rails,
Uncategorized
Here’s what I am using at the top of the view I just converted to HAML in a Rails 3 app to display any validation errors. Adjust for your own model and preferences as desired.
%h2 New Form in HAML
= form_for(@new_model) do |f|
- if @new_model.errors.any?
%div#errorExplanation
%h2= "#{pluralize(@new_model.errors.count, "error")} prohibited this new_model from being saved:"
%ul
- @new_model.errors.full_messages.each do |msg|
%li= msg
Edit 16-July-2010: It turns out that Rails 3 has a template engine that you can use to generate the views for you using HAML when you scaffold up a resource. Watch Ryan Bates’ excellent Railscast Episode 216 for more information.
Posted by admin on Jun 14, 2010 in
Rails,
Ruby,
Testing
In updating an existing Rails app to run under Rails 3 (beta 4), I realized you could indicate that a certain test case should be skipped. Literally, just add “skip” inside of the test (I added it to the top of one of mine as it was actually a work in progress) followed by an optional message. For example:
test "should take the warp core offline" do
skip
warp_core.dismount
end
Very useful.
Posted by admin on May 18, 2010 in
Business
My office is in what I refer to as “the penthouse suite” in a medium-aged building in the core old business area of Sunriver, OR. As such, I overlook one of the main two-lane roads that traverses the length of Sunriver north-south, the main part of the mall, a morsel of Mt Bachelor, and a TON of trees.
Just a moment ago, a bird lit on the extreme tippy-top of a fir tree whose peak is only a few feet higher than my office, making the tree about 9 meters tall. He landed on a treetop that is only about 1 square cm. I immediately thought to myself, “I wonder why he landed on that spot? It’s difficult to land on and difficult to hold onto. His bird feet can just barely hang on because there’s so little to hold onto. He easily could’ve landed and rested in some comfort on a lower branch.” To which I immediately responded to myself, “It obviously isn’t how comfortable he is that matters; it’s what he can see and do from there.”
My bird friend surveyed the area from there for about 60 seconds, and then he flew off — doubtless to somewhere he’d just seen from his recent perch.
I have an idea for a new logo for Standalone Code.
Posted by admin on May 15, 2010 in
Mac OS X,
Xcode
When working on an Xcode project, it’s really easy to end up with a dozen windows open. You did know that you can close all of them and leave just the main project window open, right?
Just option-click in the close “box” (that’s what we used to call it when it was square, is it the “close circle” now?) of any editor window, just not the main project window. Et voilà — all windows closed.