With many Android apps, there often seems to be little correlation between the size of the package and the value it provides. Multi-megabyte apps that do almost nothing leave me wondering, “what’s in there?”
Unpacking with dex2jar and JD-GUI often provides answers, and frequently it just means the developer forgot to enable Proguard when building. An overabundance of ill-compressed drawables are another common source. But beyond these, the habits of server-side re-use (freely expanding POMs and dropping in FOSS JARs) are a key source of bloat.
I try to be stingy when it comes to Android app libs, often taking a tougher route to avoid bringing in large JARs that might otherwise be useful. Such was the case recently when I needed to do a multi-part post to a REST web service that consumed a mix of binary image data and JSON. Multipart HTTP is conceptually simple, but the markup is obscure enough to make generating it directly from a business app just wrong.
Fortunately, though, Apache HttpMime is just 26K, and makes the process simple. For example:
MultipartEntity entity = new MultipartEntity();
entity.addPart("request", new StringBody(request));
entity.addPart("image", new ByteArrayBody(image, "image/jpeg", filename));
To avoid duplicate class errors at Proguard time, exclude the dependent httpcore in your pom.xml, like so:
I don’t always add JARs to Android apps, but when I do, I prefer light ones.
Distributing in-progress iOS apps is tedious enough: setting up signing certs, creating provisioning profiles, adding device IDs, etc. I wanted at least the end-user install step to be friendlier than syncing with iTunes and remembering the .mobileprovision file. That is, I wanted to provide the same simple install for my iOS apps as I do for Android apps, with a web page that folks can visit from their phone browser and simply click a link to download and install.
Fortunately, I came across the itms-services protocol: Apple’s solution for wireless app installs. All it takes is the distribution IPA (with embedded mobileprovision file), plist, and a web page with the link. It’s not widely known, but there are a couple of good tutorials on the web, such as Apple’s instructions and Aaron Perecki’s walkthrough. No more tangles, no more wires!
Business travels and extra duties lately have brought some unexpected surprises. I find such “out of the box” adventures refreshing: pulling the rug out from under typical routines forces me to challenge assumptions and improvise. Here are some examples from the past two days.
The Right Sequence
During group architecture sessions, I needed to quickly create, modify and display sequence diagrams to demonstrate interactions among several new web services. Lacking my usual tools (and convinced there had to be a better mousetrap), I searched around and found websequencediagrams.com. This STTCPW site was exactly what I needed. Using it was faster than tools such as Visio Pro, and even faster than drawing and editing on whiteboards.
Today I got word that some Quartz jobs weren’t running as expected during pre-production testing, where typical weekday processes were run as a logical business day on Saturday. The cron-expressions were correct, so I needed to see more. A look at the full jobs.xml revealed the culprit: this environment had been configured to use WeeklyCalendar rather than the usual AnnualCalendar. A quick temporary switch had Quartz working weekends with the rest of us.
Fog of WAR
Despite version labels and other indicators, a web app was behaving as if it was down-level in a key area. Since the WAR file hadn’t been obfuscated, I grabbed a copy of the JD-GUI decompiler for a closer look. Sure enough, the class in question was at an older level. When sources aren’t available or are in question, the JD Project tools are indispensable for moving past assumptions and getting to facts.
Decimal, with an E
New calls to my web services from VoiceObjects were sending certain decimal data in E notation. The underlying call flow objects were TTA – Literals/Digits with a digits?minlength=1;maxlength=14 grammar, so it should have been decimal from end to end. But there turned out to be an unexpected feature of the platform to convert to float whenever any arithmetic is done, with no access to DecimalFormat or other mechanisms to convert back. Since there was fortunately no loss of precision and since a problem correctly stated often solves itself, I knew exactly what to do: modify the web service to accept the format. Voxeo provides a great VoiceXML platform, but it has plenty of surprising nuances like this.