Tony Lukasavage

Caffeine. Whiskey. Code. Mostly the last one.

SVN commit that ignores unversioned files

SVN Commit Fun

I know, I know, I should be using Git. Well, I do. I use it for everything I have under my control. Unfortunately, like many, I still have obligations that require me to use SVN on a regular basis. And when I roll with SVN, I roll command line. No, its not an elitist, terminal God point of view. I happen to like TortoiseSVN, but 90% of my SVN versioned work is on Linux servers.

If you’re like me, you’ll find yourself frequently using this lazy command line syntax inside your project directory to catch all your changes in one commit:

1
svn commit * -m "you should always leave a message!"

And there’s a very good chance you’ve run into this error, or something similar:

1
2
svn: Commit failed (details follow):
svn: '/path/to/unversioned_file' is not under version control

As it turns out, there doesn’t appear to be a way to ignore unversioned files in the svn commit options. Now before you sart leaving comments about the svn:ignore property of the SVN configuration, realize that it only applies to the svn add, svn import, and svn status commands. It has no impact on svn commit calls so we need another solution.

To that end, I put together a simple one-liner shell script to perform an SVN commit on all versioned files within the current directory, ignoring all unversioned files. Here it is:

1
svn status | grep ^[^?] | awk '{print $2}' | xargs svn commit -m "my commit message"

In case that makes no sense, it performs the following operations:

  1. Call svn status to get a full list of relevant project files.
  2. The question mark (?) in svn status signifies an unversioned file. The grep regular expression only matches files that do not start with that question mark.
  3. Use awk to print the second column from the svn status call, which is the filename.
  4. Use xargs to feed the filename list from awk to our svn commit call.

You can take this all one step further (as I have) and turn it into a bash script accepting your commit message as its only argument (signified by the ${1}).

1
2
#!/bin/bash
svn status | grep ^[^?] | awk '{print $2}' | xargs svn commit -m "${1}";

There you go, happy SVN’ing.

Android Quick Tip: EditText with DONE Button That Closes the Keyboard

Android Quick Tip

Close the keyboard when you click ‘DONE’… seems like a simple task, right? Unfortunately, clicking ‘DONE’ or the ‘RETURN’ button in even a single line Android EditText will not drop focus and close the soft keyboard. In most cases it will just generate a new line of text. So what do you have to do if you want to close the soft keyboard by clicking ‘DONE’?

First you need to set the android:imeOptions attribute equal to “actionDone” for your target EditText as seen below. That will change your ‘RETURN’ button in your EditText’s soft keyboard to a ‘DONE’ button.

* example_edittext.xml

1
2
3
4
5
6
7
<EditText
    android:id="@+id/edittext_done"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:hint="Enter some text"
    android:imeOptions="actionDone"
    />

Now we need to create a custom OnEditorActionListener for the target EditText that will recognize when the ‘DONE’ button has been clicked. In it we override the onEditorAction() method, get an instance of the InputMethodManager, and use it to close the soft keyboard. Here’s the code for the custom OnEditorActionListener class:

* DoneOnEditorActionListener.java

1
2
3
4
5
6
7
8
9
10
11
class DoneOnEditorActionListener implements OnEditorActionListener {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            InputMethodManager imm = (InputMethodManager)v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            return true;
        }
        return false;
    }
}

Now go to the onCreate() method of the Activity that contains the target EditText. We’ll call it SampleActivity here. In here you will assign the new DoneOnEditorActionListener to the target EditText via the setOnEditorActionListener() method.

* SampleActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
public class SampleActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sample_activity_layout); // sample_activity_layout contains our target EditText, target_edittext

        EditText targetEditText = (EditText)findViewById(R.id.target_edittext);
        targetEditText.setOnEditorActionListener(new DoneOnEditorActionListener());

        // The rest of the onCreate() code
   }
}

And there you go, your target EditText field will now close the soft keyboard whenever you click the ‘DONE’ button. Very handy and not too difficult. Enjoy.

Android Quick Tip: Tiling a Background Image

Android Quick Tip

Often times you’ll want to tile, or repeat, a small image as the background of an Android view or layout. This is just like using the ‘background-image’ and ‘background-repeat’ CSS options, and almost as easy. First and most importantly, you’ll need an image to tile. If you don’t have one of your own, use the one below (right click and “Save Image”).

carbon_fibre.gif

Carbon Fiber tile

Now, in your project’s res/drawable path, create a file named tile_background.xml. Fill the file with the following XML:

tile_background.xml

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8" ?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/carbon_fibre"
    android:tileMode="repeat"
    />

Now all you have to do is set the android:background attribute of your target view or layout to the tile_background.xml drawable id, like so:

sample_layout.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/tile_background"
    >
</LinearLayout>

And if sample_layout.xml was the assigned content view for your main activity, you would see this when you started your app:

tiled

Android Quick Tip: Remove ListView Dividers

Quick Tip

If you want to remove the dividers from an Android ListView, execute the following code on your ListView object.

1
2
3
ListView listView = (ListView)findViewById(R.id.your_listview_id);
listView.setDivider(null);
listView.setDividerHeight(0);

or if you are trying to remove dividers from a ListActivity, do this in your onCreate() method:

1
2
this.getListView.setDivider(null);
this.getListView.setDividerHeight(0);

And there you go, no more dividers. Enjoy.

Review: PhoneGap is Web-based, Appcelerator is Pure Javascript

What’s The Difference?

I’ve seen a lot of confusion out there on what the actual distinction is between PhoneGap and Appcelerator Titanium in terms of programming. Both state that they provide cross-platform mobile development frameworks driven by a Javascript core.  How different can they be?  Turns out, very.

The fundamental difference is that PhoneGap is a web based solution where Appcelerator Titanium is a pure Javascript API that creates native code.  As I’ve gone over the differences between these 2 in detail before, I’m going to very strictly stick to the topic of how their code works. Since people seem to love charts so much, here’s a quick review to show the divergence between the two frameworks:

  PhoneGap Appcelerator Titanium Notes
Javascript API PhoneGap’s API interacts as typical JS does in your web code. Appcelerator Titanium API is NOT web code, it is used to interact with native code.
Supports HTML5/CSS3 PhoneGap is a web app that runs in a native web browser view.
Supports Web Standards PhoneGap looks, feels, and develops like a standard web page. It is also subject to the same browser compatibility concerns.
Supports DOM based
JS libraries
JS libraries that reference the DOM, like jQuery, Prototype, or any of the new <canvas> based libs will only work with Appcelerator Titanium webviews
Native Code Appcelerator Titanium creates a truly native app via a JS API that maps to native code.
Native UI/Performance Appcelerator Titanium performance is limited only by the device. PhoneGap’s is limited by the device’s web view.

What Does This Mean?

  • Web developers will have a much easier transition going to PhoneGap than they would Appcelerator Titanium.
  • Application developers without serious web development chops will likely gravitate towards Appcelerator Titanium. Why learn HTML, CSS, and Javascript when you can just learn Javascript?
  • Designer work will be tougher to integrate into an Appcelerator project as all the layouts and assets are done programmatically. PhoneGap, on the other hand is effectively web development, which designers have been working with for a very long time.
  • Appcelerator is always going to win on performance.
  • There will be an inevitable flood of web developers calling themselves mobile developers because they are familiar with PhoneGap. Beware.
  • Appcelerator has a much deeper and more complex integration with each mobile platform.
    • Pros: Native look, feel, and performance
    • Cons: Platform compatibility will be achieved more slowly. Much harder to “code once, deploy everywhere”.

Summary

The above is a hyper-condensed review of the whole story. As always, I encourage you to try both of these platforms. They both excel in many areas and offer unique features. Neither is the wrong choice, but depending on your scenario, one might be better suited than the other.

Display Images from the Internet in Android

The Overview

I’ll make my usual yammering quick so you can get straight to the good stuff. This is just a snippet to show you how you can display an image from the Internet in your native Android app via ImageView. This is ideal in a few situations, namely when you need to keep app size and initial load time down, or if it isn’t feasible to locally store all the images your app will use.


The Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.savagelook;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.ImageView;

public class ShowImageActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // YOUR_LAYOUT is the name of your layout resource
        // IMAGEVIEW_ID is your ImageView in YOUR_LAYOUT
        setContentView(R.layout.YOUR_LAYOUT);
        ImageView imageView = (ImageView)findViewById(R.id.IMAGEVIEW_ID);

        imageView.setImageDrawable(createDrawableFromURL("http://savagelook.com/misc/sl_drop2.png"));
    }

    private Drawable createDrawableFromURL(String urlString) {
        Drawable image = null;
  try {
      URL url = new URL(urlString);
      InputStream is = (InputStream)url.getContent();
      image = Drawable.createFromStream(is, "src");
  } catch (MalformedURLException e) {
      // handle URL exception
      image = null;
  } catch (IOException e) {
      // handle InputStream exception
      image = null;
  }

  return image;
    }
}

9 things to know about PhoneGap

The People

As it turns out, the co-founders and core developers of PhoneGap are pretty accessible guys.  Who better to know when it comes to using a framework than the authors?  Everything from basic “getting started” questions to more complex topics from me have been addressed directly by one or more of their team.   While there’s probably a ton of people I’m not mentioning, these few guys in particular have been exceedingly helpful.

I’m a Twitter fiend so that’s generally where I find these guys, but make sure you also check out their google group and IRC.  I’ve said this before… if you are doing PhoneGap development and aren’t following this crew on Twitter, then you’re an idiot.

PhoneGap Build

So you hear about all these frameworks that do cross platform mobile development, “code once, run everywhere”, and everything just magically works.  Well… it ain’t that simple.  You’ve got SDK installations, developer & signing certificates, build chains, and custom project layouts to worry about with each platform.  While this can become a nightmare to manage, PhoneGap makes a pretty epic effort to help with their currently free, beta service called PhoneGap Build.

PhoneGap Build will allow you to give them the web code that drives your app and in return you will get App Store deployable binaries back for all the platforms listed in interface snapshot above.  You don’t have to install all the SDKs.  You don’t need to worry about any platform specific setup.  It is actually that simple.

I highly suggest setting up an account right this second, especially if you are just starting out as a mobile developer.  The time consuming, and often frustrating, nature of multi-platform testing and deployment is easy to underestimate.  When you’re learning the ropes of mobile APIs and the finer points of app creation, the last thing you want to worry about is every individual SDK’s varying degrees of compatibility.  Which leads me to my next section…

PhoneGap Generate

If you are like most mobile developers, you are a (proud) owner of the 4+ GB behemoth of a download XCode 4.  The good news is that you can build apps for iOS 4+ with it.  The bad news is that XCode 4’s default configuration settings are not compatible with PhoneGap, and it can be a bit complicated to resolve.  Here’s the bloody path I took to get XCode 4 building my PhoneGap apps.

But in their constant efforts to make the build process easier on developers, PhoneGap came up with a short term solution.  Instead of hacking up your XCode 4 project files, let PhoneGap do it for you!  Enter PhoneGap Generate.  Its an extension of the PhoneGap Build site that will, given a project name, generate an XCode 4 compatible project for you.  While it’s not an ideal situation, it can save you some of the headaches I endured trying to do it myself.  Hopefully the PhoneGap distribution will have this resolved in the near future.

Cordova

Now we’re getting to the real goodies.  Cordova is without question the single biggest boost to my PhoneGap development workflow.  Think PhoneGap Build with no need for the cloud.

Cordova, in Brian Leroux’s (author) own description, is

A PhoneGap project toolchain that automates common tasks for building cross platform mobile projects with OS X. Automate common development workflow tasks such as: compiling, debugging, testing, releasing and other things in between. As an added benefit projects generated with Cordova create a consistent, predictable, easy to understand and therefor extend software project. A number of conventions are introduced removing the need for mobile developers to relearn their tools or, worse, rebuild them for every project.

Be warned, Cordova is young and best used by those with a good understanding of how PhoneGap works in terms of project layout, building, testing, and deployment.  It also helps a great deal if you understand these concepts as they relate to each platform (i.e., Android, iOS, Blackberry, etc…) you plan to target.  And you’ll need to me comfortable with the Terminal on Mac OS.  If I haven’t scared you off yet, read on.

Basically, you can build and test PhoneGap apps for multiple platforms with simple Terminal commands.  No more creating projects in XCode or Eclipse just to conform to a specific platform.  You can choose your favorite web development IDE (Aptana for me) and do all your work there.  When you’re done, just run one simple command from the command line and it will build for iOS, Android, and even Blackberry (with a Windows VM).  Check out this short demo from Brian Leroux to see what I mean.

Yeah, its low level and it doesn’t have a pretty GUI, but man this project has massively improved my efficiency in terms of cross platform testing.  I’m hoping more people see this project and hop on board, and even contribute like I did (Blackberry support).  A tool like this can really be a game changer in terms of what a single developer can do for a mobile app spanning a multitude of platforms.

You don’t have to use Platform-specific IDEs

Web IDEs

According to the PhoneGap docs on the “Get Started” page, I need XCode if I want to build iPhone/iPad apps, Eclipse for Android, a Windows based IDE for Blackberry, its a serious pain in the ass.  But these are web based solutions, right?  Why in God’s name would I want to endure XCode and Eclipse as web development IDEs?!  I wouldn’t, and I don’t have to.

You’ve got 2 options when it comes to developing your apps if you don’t want to use the platform specific IDEs (and you shouldn’t).

  1. Develop your web code in your IDE of choice.  When its at a point you want to test it on a specific platform, copy the web code into a PhoneGap project built in the platform specific IDE.  For example, if you like TextMate, do all the web coding in TextMate and when you are ready to test it on Android, copy the web code into the assets/www path of your Eclipse Android project.  Run and test from there.
  2. Use Cordova. You can do your web code in your IDE of choice and simply run ‘make debug’. In the current incarnation of Cordova, this will open your web code in the iPhone, Android, and Blackberry simulators.  Reference the Cordova Github README.md for more details on usage.  In the near future I’m planning a blog post on that very subject.

The long and short of it is that the platform specific IDE workflows are not optimal for web development.  Find the tools that best suit you and your web development style, use them, and only spend your time in platform specific IDEs when necessary.  The time you save using a full featured, web-focused IDE makes up for the less-than-fun process of having to copy and paste code to platform specific IDEs.  You save even more time if you use Cordova.  Have I pimped Cordova enough yet?

The Supported APIs (per platform)

So as you probably already know, you can find all of PhoneGap’s documented mobile API support at docs.phonegap.com. What you might not be aware of is that they have done a really good job of documenting which APIs are supported by which platforms.

On a function by function basis, the “Supported Platforms” section lets you know down to the OS version which platforms support it.  The trailing “Quirks” section let’s you know which platforms may not behave as expected.  Not only that, but the “Quirks” are typically accompanied by workarounds to make your life a little easier.

If you are doing cross platform mobile development, get used to the fact that you are going to be spending time dealing with inconsistencies, regardless of framework choice.  Having documentation with this level of detail will surely decrease that time, as well as prevent you from hitting unforeseen dead-ends in your app development.  RTFM, its worth it.

PhoneGap can technically do anything

PhoneGap does its best to expose platform specific mobile APIs in a bare bones, clean, abstracted manner.  While this does create a reliable experience in development, it does leave some things you might want off the table.  The big thing, for example, is native UI components.  While “native” anything seems to be contradictory to  cross platform development, its still a common request (see Appcelerator or even this PhoneGap based solution).  So how do you go about offering platform specific functionality in a PhoneGap app?  With plugins.

Plugins allow you to write native code for a specific platform in order to extend the PhoneGap framework.  For example, you could write code for handling bar code scanning in Java for Android, then write some Javascript to hook your native code to the PhoneGap framework, then use this native functionality in one of your PhoneGap apps.  OK, I didn’t give an entirely clear account of what is necessary, so just reference the PhoneGap wiki for details on plugin development.  The wiki currently contains step by step instructions for Android, iOS, and Blackberry.  Here’s the resources you should be checking out.

They Want You!

PhoneGap is an open source project.  Very open source in fact.  As though the BSD or MIT licenses weren’t liberal enough, PhoneGap gives you the choice of applying either to your work.  As long as you keep their copyright notices in your code and don’t use their name to promote your product, you can use their code however you wish, commercially or otherwise.

How does PhoneGap benefit from this? Well, licensing like this tends to create bi-directional generosity.  By this I mean the community commonly contributes to PhoneGap and its plugins and tools.  You can go to Github right now and fork your own copy of the whole PhoneGap framework (among other things) at the PhoneGap Github account.

So if you use PhoneGap and write some custom code you think others can benefit from, consider giving back to keep the spirit of open source alive.  Otherwise you’re a jack ass.

weinre

Can’t believe I forgot this one. I’ll make this brief as your best bet is to read more at its website: (http://pmuellr.github.com/weinre/).

Basically, weinre lets you debug web pages remotely. What does this mean for PhoneGap? This means you can debug your native PhoneGap apps either on device or simulator. It alleviates one of the biggest time sucks of web based mobile development, which is the silent dismissal of malfunctioning Javascript calls. But now instead of your exceptions going the way of /dev/null, you can debug and log your execution as you would any other application. Oh, and Cordova has weinre built in.

A Deeper Look at Appcelerator and PhoneGap

Overview

I’d like to start by saying that I think it’s important that both of these frameworks exist.  The more I worked with each, the more I found that it wasn’t a simple question of which mobile framework was better.  Both have some of the features a cross platform framework should have, and each shines in areas that the other frankly does not.  And that will be the focus of this analysis.  What are the key aspects to a great cross platform mobile framework, and how do Appcelerator and PhoneGap stack up.

Cross Platform Support

So this is why we’re all here right? Code once, run every where.  That’s what we want.  Well in this case, one of these solutions gets you a lot closer than the other.

This is PhoneGap’s bread and butter.  By leveraging web views native to the mobile devices, PhoneGap allows you to build as an app as complex and modern as you want while providing the ability to have it gracefully degrade for lower end devices, all in the same code base.  This degradation can be controlled via CSS or even dynamically with javascript and media queries.  You can use the same design and development principles that have guided cross browser development for years.  And the list of mobile platforms they support (which includes iOS, Android, Blackberry, webOS, and Symbian)  is definitely worth bragging about.

Appcelerator, on the other hand, does iOS really, really well.  Android brings some additional headaches and quirks.  Blackberry is still in the beta stage.  They are actually creating native code based on their Javascript API, so the quirks will likely always exist. Appcelerator will constantly be one step behind/removed in their efforts to integrate native functionality.  No fault of their own, it’s just the nature of their product.

This is why I think emphasis on Appcelerator being a cross platform framework is misleading.  While it CAN be a cross platform framework, it is not by nature.  I mean, how can it be? One of its main selling points is access to native UI components, something that is obviously not part of a cross platform solution.  One code base for multiple mobile platforms is totally a possibility with Appcelerator, but you will likely sacrifice a lot of what makes it great (coming in the following sections) to get to that lowest common denominator.

Defined Workflow

The product will only be as good as the tools that support, particularly when you are trying to appeal to an audience as large as mobile developers.  In this respect, Appcelerator is the clear winner.

Earlier this year Appcelerator announced that they had acquired the web development IDE Aptana. Before this point you were stuck with Titanium Developer which did the job, but was only a project deployment tool, not a true IDE.  Just this month they introduced the first version of the new Titanium Studio, an integration of Titanium Developer and Aptana.  There were a few bugs to wrestle with the earliest versions of this software, but I must say that I am loving it.  It has truly integrated the development and deployment workflow, making it more organized and efficient.  It has built in update checking for not only the studio but also the Titanium SDKs.  Oh, and did I mention that all of this is free?

PhoneGap leaves you to your own tools and workflow.  A plus for some, but I would imagine its a minus for those of us who don’t come from primarily a web development background.  They give you some direction in the Tools section of their website, but its not what you would call a workflow.  It a different approach, basically leaving the developer to determine what libraries, IDE, touch frameworks, etc… are most appropriate for their project.  This can be problematic for two reasons. 1, new mobile developers are not going to know which tools are the most appropriate and 2, there are A LOT of available touch and JS libraries out there for mobile development.  Choosing can be a project in its own rite. All that said, Brian Leroux of Nitobi, the makers of PhoneGap, created the XUIJS library. Its what I’m using and I’m really digging it so far.

Programming Language

Admit it Appcelerator developers, you aren’t interested in the Javascript API so much as you are interested in NOT writing Objective-C!  Yeah, me too.

You would think this topic would be a deadlock, right?  Its just Appcelerator’s Javascript API versus PhoneGap’s use of the standard web stack of HTML/CSS/JS.  It basically the same thing… or is it?  Remember how I said in the last section that PhoneGap gives you free reign to choose whatever framework you want for development?  Well, Appcelerator doesn’t, and it is definitely to the chagrin of many Javascript savvy developers.

PhoneGap is HTML/CSS/JS.  Anything you can do with it on a normal web page you can do in a mobile browser’s web view.  This means any chunk of Javascript you find anywhere that you like can potentially be integrated into you app.  This ranges from your favorite frameworks like jQuery and Prototype, mobile  libraries like Sencha Touch, or even graphical ones like Grant Skinner’s EaselJS or one of these many 3D libraries.  Performance and device support permitting, you can use any Javascript you want.

Appcelerator’s API unfortunately is purely Javascript, is has no ties to the DOM.  But wait, doesn’t the most popular Javascript library in the world assume the presence of the DOM window and document?! Yep, that’s right, you can’t use any part of jQuery that requires the DOM (which is almost all of it) in your Appcelerator code.  The one exception is that you can still use jQuery and other DOM reliant libraries in a Titanium.UI.WebView, but you can’t use it with the actual Appcelerator API.  Annoying to me, but I can see this being REALLY aggravating  to long time web developers accustomed to using jQuery with everything.

Deployment Support

If you’ve spent any time in mobile development, you know that deploying your finished app to markets and app stores can be a truly daunting task.  There’s certificates, app signing, icons, logos, promotional images, supporting text, and the task of keeping it all organized.  It can quickly become a mess.  While both Appcelerator and PhoneGap both give you detailed instructions on how to build app store ready apps from your development environment and offer professional services, PhoneGap takes it one huge step further.

PhoneGap Build is currently a free beta service that you need to get your ass signed up for now.  While I highly encourage you to check it out for yourself, here’s the insanely easy workflow:

  1. Upload you PhoneGap project to PhoneGap Build (or use its Github integration)
  2. Configure your platform specific accounts with certificates and signing keys (all PhoneGap supported platforms available)
  3. Watch as PhoneGap Build creates deployable binaries for each of these platforms and delivers you download links for each

Now that is the type of workflow I’m looking for! A quick note on step #2 is that iOS is the only platform that requires a certificate to get a testable binary.  You’ll want to set up certificates and keys before you deploy the the market/app store, but you can test the binary without them.

Speed of Development

All this flexibility and platform support has to bite PhoneGap in the ass somewhere, right?  Speed of development, if you can’t tell by it name, is another place that Appcelerator excels.

Appcelerator allows developers to start building an app that looks, feels, and performs like a native one very quickly.  Some of the big reasons are the following:

  • Their Javascript API is infinitely easier than Objective-C, and some might also say Java (but not me)
  • Tons of ready-to-use native UI components
  • You are not required to adhere to the MVC architectural pattern
  • The double-edged sword of loosely typed Javascript allows you to create custom components like table views and rows very easily
  • The new Titanium Studio gives you one place to develop and build for multiple platforms

 

PhoneGap, though, is a bare bones framework.  It looks to provide mobile API support (things like location, accelerometer, etc…) across all major vendors.  The UI is left up to you and your chops as a web developer.  To that end most people are left to go find another touch framework to layer on top of PhoneGap.  Sencha Touch, jQuery Mobile, JQTouch are all popular options.  There’s even efforts to create web based “native” components.  You can also take my route and build most of it from scratch using XUIJS.

The long and short is that if you are only building for iOS, or maybe also Android, Appcelerator will likely get you from concept to completion faster than PhoneGap.

Documentation

Documentation is key when undertaking any new technology.  Both frameworks have their ups and downs here.

Appcelerator maintains a newly improved collection of there documentation on their new Confluence site.  While it is fairly comprehensive, it is also a bit jumbled, particularly the “Getting Started” section.  Its all there if you have the patience to find what you are looking for.  You’ll find installation, setup, examples, tutorials, the works.  You can also find a comprehensive listing of their mobile API here.  The problems I see with their documentation are the following:

  • Its sometimes hard to tell what version of their SDK examples apply to
  • Often Titanium objects have properties that don’t apply, or don’t behave as the documentation indicates
  • You are sometimes left digging through the Q & A section to find the quirks for specific Titanium objects
  • Examples given for Titanium objects are WAY too simplistic
  • How ‘bout a few more “Hello, World!” scale tutorials before you throw us at the Kitchen Sink?!
  • Im sure this will change after the Titanium Studio release gets some traction, but the “Getting Started” section is still using Titanium Developer as its chosen workflow

PhoneGap’s “Get Started” section is a thing of beauty.  In a very clean, concise layout, the PhoneGap site walks you through how to set up your computer for each individual platform you wish to develop for.  It list requirements, toolsets, and easy to follow instructions.  It helps ease the intimidation that can come with trying to develop for so many platforms. Once you get it up and running, PhoneGap’s API documentation is incredibly easy to follow.  A simple layout lists everything PhoneGap is capable of doing.  Clicking on these capabilities then takes you to the API specific documentation that lists usage, examples, device support, and any quirks that are currently known.  It takes a lot of the guess work and frustration out of the inevitable troubleshooting that ensues with cross platform mobile development.

 

PhoneGap definitely shines in the documentation department.  In all fairness, though, Appcelerator has a hell of a lot more to document.  PhoneGap’s lack of UI components accounts for a large part of its documentation being so easy to follow.

Community

An active and knowledgable community is one of my biggest factors in choosing any technology.  Appcelerator and PhoneGap both have a wiki and blog, and also offer these a few more resources.

Appcelerator has their Q & A section of their site.  It allows users to submit questions about Appcelerator to the community.  Users can submit answers, vote on others’ answers, and receive points and badges for participation.  If StackOverflow has taught us anything, its that people like being rewarded for participation, no matter how meaningless.  On top of this free resource, they also offer training, certification, and professional services for those looking to take their Appcelerator’ing to the next level.  I hand out on Twitter a lot, so its worth mentioning that you can get some great help and info regarding Appcelerator by following @appcelerator, @fusion94, @aaronksaunders and @chadauld.

PhoneGap maintains a connection with the community with their Google Group and on IRC at irc.freenode.net #phonegap.  They also offer professional services and training.  The core of the PhoneGap team is very involved with the community and I’ve often been found chatting with @phonegap, @andrecharland, @brianleroux, and @davejohnson on Twitter.

Other than wishing PhoneGap had some kind of a forum system better than a Google group, I think both frameworks do a very good job of listening to and staying engaged in the community.

Extensibility

No developer I have ever known is just happy with the tools he’s given.  We want to be able to add to and modify anything we get our hands on.  Both frameworks are very extendable via modules and offer open source licenses, though PhoneGap’s option of “New” BSD or MIT license is a little nicer than Appcelerator’s Apache 2.0 license.

Appcelerator offers Android and iOS module development guides.  These allow you to build native components in their native SDKs and then be able to access them in your Appcelerator app via the Javascript API.  Anywhere Appcelerator falls short in terms of supporting any API or UI component, you are free to pick it up and make it happen.  Its not the simplest process and effectively removes the possibility of  cross platform code, but can be a strong tool for a single platform scenario.

UPDATE: In addition, Tony Guntharp also gave me this blog post detailing how modules can be developed in other languages as well: http://developer.appcelerator.com/blog/2011/04/tiphp-tipython.html

PhoneGap also supports additional modules, or plugins, to its framework in the same fashion that Appcelerator does.  You can develop native code and then write hooks back to PhoneGap to access it in your project.  Again, this undoes any cross platform compatibility unless you make the native component for all supported platforms.  There’s a guide to creating plugins found here.

Appcelerator on Github: https://github.com/appcelerator PhoneGap on Github: https://github.com/phonegap/phonegap

Summary

So as I stated at the beginning, I think both of these frameworks are important and have their place in the mobile landscape.  From my personal perspective, as they both stand now, PhoneGap is the true cross platform solution.  Brian Fling, author of “Mobile Design and Development”, rang the point home throughout his book that the future of mobile development lies in web based applications that adhere to a structure of graceful degradation.  I initially thought he was a web developer who didn’t want to learn Objective-C or Java.  After spending some time with native development and multiple cross platform frameworks, I find myself coming to the same conclusion.

But that’s not to say that PhoneGap is the end all, be all of mobile development.  I happen to think that for iOS & Android projects, Appcelerator could likely be your best choice.  Unless you have prior experience with Objective-C, I would advise anyone with even a basic knowledge of Javascript to give it a shot before resorting to native development.  Trust me, you won’t miss Interface Builder, and outlets, and actions, and all kinds of other iOS MVC fun.  Oh, and you’re sure to enjoy the native UI and performance that Titanium uniquely provides.

NOTE: I would have liked to include Adobe Air as I did in my past comparison, but I honestly have not used it in 2+ months and there have been serious changes since.  I’ve been focusing on cross platform solutions that can hit the big three mobile devices out there: Android, iOS, and Blackberry.  Soon as Blackberry supports Adobe Air you better believe I’m coming back to re-evaluate it.  I’ll take AS3 and/or Flex over HTML/CSS/JS any day.

Swipes, or “Flings”, for Navigation in Android

Download the Project

Overview

I’ll keep the narrative on this one brief and get you right to the good stuff. I wanted to be able to navigate through the activities in an Android app just like Tweetdeck. One swipe of the finger and you quickly transition to the next column. Take a look at how it looks when you swipe your finger from right to left.

In Android, they call this a “fling”. Think of a fling as a touch and drag with a specific direction and speed threshold. Once that speed threshold is surpassed, the fling is triggered. Here’s the bare bones code necessary to get fling gestures working in your Android app. Also, I use custo animations based on the ones from the Android SDK to determine how my activities will transition. A left to right fling should obviously have the opposite appearance as a right to left fling. Big thanks to this post as it makes up a majority of the logic and code in this sample.

src/MainActivity.java

This is where the heavy lifting is done. The important things to note are the use of a custom gesture listener to handle our fling event and the use of overridePendingTransition() to apply our custom transition animations to the activity we just started.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.savagelook;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View;
import android.view.MotionEvent;

public class MainActivity extends Activity {
    private static final int SWIPE_MIN_DISTANCE = 120;
    private static final int SWIPE_MAX_OFF_PATH = 250;
    private static final int SWIPE_THRESHOLD_VELOCITY = 200;
    private GestureDetector gestureDetector;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        gestureDetector = new GestureDetector(new MyGestureDetector());
        View mainview = (View) findViewById(R.id.mainView);

        // Set the touch listener for the main view to be our custom gesture listener
        mainview.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                if (gestureDetector.onTouchEvent(event)) {
                    return true;
                }
                return false;
            }
        });
    }

    class MyGestureDetector extends SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
      Intent intent = new Intent(MainActivity.this.getBaseContext(), MainActivity.class);

            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
                return false;
            }

            // right to left swipe
            if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
          startActivity(intent);
          MainActivity.this.overridePendingTransition(
          R.anim.slide_in_right,
          R.anim.slide_out_left
          );
          // right to left swipe
            }  else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
          startActivity(intent);
          MainActivity.this.overridePendingTransition(
          R.anim.slide_in_left,
          R.anim.slide_out_right
          );
            }

            return false;
        }

        // It is necessary to return true from onDown for the onFling event to register
        @Override
        public boolean onDown(MotionEvent e) {
              return true;
        }
    }
}

res/layout/main.xml

A standard main.xml. The only change you’ll find here is that we’ve given the main view, our LinearLayout, an ID so it is accessible in MainActivity.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/mainView"
    >
  <TextView
      android:layout_width="fill_parent"
            android:layout_height="wrap_content"
      android:text="@string/hello"
  />
</LinearLayout>

AndroidManifest.xml

Again, a standard manifest with one small change. I added android:noHistory=”true” so that as we load new activities with each fling, the view stack doesn’t grow out of control. You can remove this if you would like to go back to a previous activity after each fling using the back button.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.savagelook"
      android:versionCode="1"
      android:versionName="1.0">

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name"
                  android:noHistory="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

res/anim/slide_in_right.xml

This along with the next 3 animations are the custom transition animations used to move our activities in and out with each fling. They are just copies of the animations in the Android SDK. In my case, they were found in ANDROID_SDK/platforms/android-8/data/res/anim. Create your own anim folder under res in your project and add these there.

1
2
3
4
5
6
<set xmlns:android="http://schemas.android.com/apk/res/android">
  <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

res/anim/slide_out_right.xml

1
2
3
4
5
6
<set xmlns:android="http://schemas.android.com/apk/res/android">
  <translate android:fromXDelta="0" android:toXDelta="50%p"
            android:duration="@android:integer/config_mediumAnimTime"/>
  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

res/anim/slide_in_left.xml

1
2
3
4
5
6
<set xmlns:android="http://schemas.android.com/apk/res/android">
  <translate android:fromXDelta="-50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

res/anim/slide_out_left.xml

1
2
3
4
5
6
<set xmlns:android="http://schemas.android.com/apk/res/android">
  <translate android:fromXDelta="0" android:toXDelta="-50%p"
            android:duration="@android:integer/config_mediumAnimTime"/>
  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

Summary

Its a little more work than you might expect for this functionality, but you do get a lot of opportunities to tinker with it. You can change the speed threshold for when flings occur. You can change both the current and incoming transition animations. You can even get creative and make transitions based on vertical or diagonal flings as well. Thats the beauty, and sometimes curse, of Android: near infinite flexibility.

Mobile Developer’s Icon & Image Checklist

Overview

If there’s one thing I’ve learned from delving into iOS, Android, and Blackberry app development, it’s that there’s a lot more to creating a mobile app than just coding it. One of the things that can catch you off guard, especially if you are devoid of design ability like me, is the amount of icons and images necessary to deploy your apps. This becomes even more daunting when you intend to deploy to multiple platforms.

The other concern is that it isn’t always evident from the development tools how many different graphics you need to account for all scenarios. A new iOS developer will likely be unaware that you need a 58x58 pixel icon for iPhone 4 Spotlight and Settings. To attempt to alleviate some of this confusion, I put together these charts to detail what I know so far about the graphics required for submitting mobile apps to the various Android, iOS, and Blackberry markets.

Icons

Android iOS Blackberry Playbook Notes
29x29 iPhone Settings and Spotlight, iPad Settings
36x36 low pixel density icon
48x48 medium pixel density icon
50x50 iPad Spotlight. iOS will trim 1 pixel off each side and add a drop shadow, making it 48x48
57x57 standard iPhone icon
58x58 iPhone 4 Settings and Spotlight
64x64 optional small custom document icon
72x72 Android high pixel density icon, iPad icon
86x86 standard Playbook icon. It will trim 5 pixels off each side, making it 76x76
96x96 Potential icon size if iPad gets a high ppi screen
114x114 standard iPhone 4 icon
144x144 Potential icon size if iPad gets a high ppi screen
320x320 optional large custom document icon


Distribution Images

Android Market Apple App Store Blackberry App World Amazon App Store Notes
screenshot sizes 320x480, 480x800, 480x854, 1280x800 iPhone: 320x480, 480x320, 320x460, 480x300 iPhone 4: 640x960, 960x640 iPad: 768x1024, 1024x768, 748x1024, 1004x768 640x640 or smaller 480x854, 854x480 required # of screenshots: Android: at least 2 Apple: at least 1 Blackberry: 1-50 Amazon: 3-10
114x114 device icon
180x120 Promotional graphic (no alpha)
480x480 Product icon that should match your 86x86 icon
512x512 Large/High resolution product icon
1024x500 Feature graphic for market

Additional Notes

For Android, your 36x36, 48x48, and 72x72 pixel icons should be placed in the drawable-ldpi, drawable-mdpi, and drawable-hdpi folders of your Android project respectively. Be sure to specify the name of the file you will be using in the android:icon attribute of the element in your AndroidManifest.xml file. Android also allows you to include a promotional video.

For iOS you simply need to add your appropriately sized and named icons to your Resources directory in your XCode project. Here’s a mapping of the icon sizes to the required name of the icon file. NOTE: There is purposely no extension on the 512x512 iTunesArtwork file.

  • 29x29 - Icon-Small.png
  • 50x50 - Icon-Small-50.png
  • 57x57 - Icon.png
  • 58x58 - Icon-Small@2x.png
  • 72x72 - Icon-72.png
  • 114x114 - Icon@2x.png
  • 512x512 - iTunesArtwork

For Blackberry Playbook, you need to specify the name of your 86x86 application icon in your application’s blackberry-tablet.xml file. Below is a sample of how you would set that up.

1
2
3
4
5
6
7
8
<qnx>
    <icon>
        <image>86x86.png</image>
    </icon>
    <publisher>My Company</publisher>
    <category>core.games</category>
    <splashscreen>my_splashscreen.jpg</splashscreen>
</qnx>

For the Amazon App Store you can also submit promotional images of various sizes and up to 5 promotional videos.

Summary

So as you can see, you’ve got a lot to consider when it comes to presenting your mobile application to the masses. As a developer, I’m looking for the simple solution here. For me, the easiest thing to do was use this 512x512 iOS icon template, create my icon, and scale it down to all the required sizes. If you happen to be reading this post and know a better/easier workflow, please let me know.

Here’s a few references to check out to get some additional information on mobile app icons and market images: