Someone read my mind!

Wouldn’t it be great to have a drawing program on the Macintosh which, after you’ve composed the artwork, can export the drawing commands for Cocoa’s Quartz or the iPhone, so you can cut and paste code to draw the same thing in your program?

I thought that would be so cool. And now it turns out someone beat me to it: Opacity.

Now if only there were exporters for Java AWT, Android’s UI toolkit, and Microsoft Windows…

Why I hate custom protocols over HTTP.

One recent trend is to use HTTP in order to send data between a client and server. Between protocols built on top of SOAP and XML/RPC (and yes, I’ve built code on top of XML/RPC, and have a Java XML/RPC library), it’s not all that uncommon to send text commands over HTTP.

And it makes sense: HTTP generally is not blocked by various internet providers while other ports are firewalled, and it is well supported across the ‘net.

As a rule, however, I’m generally opposed to overriding an existing protocol for private use. My instincts are if it is possible for me to open a port from a client to the server that is not in use by an existing protocol, then use that port instead.

With HTTP, there are a number of downsides. HTTP is essentially a polling protocol: ask a question, wait for an answer, get an answer. There is a lot of plumbing that has gone into HTTP in order to work around the performance issues revolving around HTTP–but because it is essentially a polling protocol, there is little you can do to bypass a resource that takes a long time to download besides opening up a second connection. (Protocols like LDAP allow multiple logical connections over the same physical TCP socket.)

HTTP has also become somewhat more complicated over the years, with things like optional keep-alive settings and an array of possible return codes. All of this makes sense if you’re building a web browser (though some of it is a bit over-engineered: I don’t know if 418: “I’m a teapot” is a joke or a sarcastic response to things like 449: “Retry With”), but for a simple RPC protocol, we really don’t need more than “success”/”failure”/”exception.”

And today I learned another thing that just confirms my “don’t override someone else’s protocol; just build your own” instinct.

As designed the client I’m working on initialized a connection by requesting information on static resources that may have changed. So I’d do an “init” call, and wait for a response. As part of the request call, the server team specified that I should send “if-modified-since” with the date of the last response, so I can tell if I should update the cached response. (This was modified from the original idea, which was to simply use an integer version.) This client runs on Android both over WiFi and over the cell network.

You can guess what happened next.

Yes, T-Mobile rolled out a new proxy server to reduce 3G network traffic by automatically detecting and caching server responses, and sending ‘304’ errors on the init call. Well, if you send ‘if-modified-since’, you better process 304 errors, right?

My client didn’t.

And so it means the 130,000 people running our client software–died. Hard.

The first time you run the application it would sync up just fine. But the next time you’d hook up, T-Mobile would detect that your request hadn’t changed, and would send a 304 response–which the client would not understand, and eventually shut down claiming the client could not connect to the server.

And we never tested this. Of course we never tested this. Our server never sent the 304 exception, and so we never had a way to test this. In retrospect, of course “everyone knows” that if you send an if-modified-since, you should process the 304 exception.

The fix was simple, as all such things tend to be once they are discovered and understood.

But it would never happened if we had never overridden an HTTP protocol, where there are layers we don’t fully understand (until they break) running on a network which can insert any ol’ proxy (some with bugs we may never understand) between the client and the server.

ColorPicker

So the designer I work with gives me colors to use in our application as a web hex color specification, and I need to put it into my iPhone application as RGB values in the range [0,1]. Or I need to pick some color, and I pick an H=210° color, but I need to plug in the color into my application as integer RGB values. Or I need to type in [UIColor colorWithRed:xxx green:yyy blue:zzz alpha:1.0], and I’ve got r=110, g=250, b=155.

So out goes the calculator, and a lot of “155 [Enter] 255 [div]” and typing in the first three digits past the decimal place.

I’m a programmer. I can create tools.

So I built ColorPicker, a Macintosh-only program which allows you to set and adjust colors, and copy them in four different ways, so they can be quickly pasted into Mac, Windows or Java code.

Redistribute as you please, hopefully it will be useful to folks.

Automatic build numbers in Xcode

This one is a relatively simple mechanism for automatic build numbers. This increments the build number every time a successful build is made in Xcode.

Step 1: Create a new Run Script

In the target setting, add a new Run Script after the Link Binary With Libraries. Change the shell to /usr/bin/perl -w and paste the following script:

# Auto increment version number from build common file

use strict;

die "$0: Must be run from Xcode" unless $ENV{"BUILT_PRODUCTS_DIR"};

# Get the current revision number and use it to set the CFBundleVersion value
open FH, "build.count" or die;
my $version = join("",);
close(FH);

++$version;
print "Build $versionn"; 

open FH, ">build.count" or die;
print FH $version;
close(FH);

$version = "1.0 ($version)";

# Update info.plist in build product. Use defaults command

my $INFO = "$ENV{BUILT_PRODUCTS_DIR}/$ENV{WRAPPER_NAME}/Info";
my @defaults = ( 'defaults', 'write', $INFO, 'CFBundleVersion', "'$version'" );
exec @defaults;

Note: If this is for a MacOS X application instead of an iPhone application, then the third to last line should be:

my $INFO = "$ENV{BUILT_PRODUCTS_DIR}/$ENV{WRAPPER_NAME}/Contents/Info";

Step 2: Create the Build Count file.

Note that this Perl script pulls the version number from a file “build.count” which is at the same directory level as the project file. You should create a file containing the single character “0”.

Step 3: Build

Now you can test to make sure that the CFBundleVersion setting in the Info file is updated to “1.0 (1)”, “1.0 (2)”, etc. (The “1.0 ” part is set by the build script; change there to update the major/minor build numbers, or prefix the build with anything you want.)

This works by incrementing the build number in the build.count file, then using the defaults command-line tool (‘man defaults’ for more) to update the info.plist file after it is copied into the executable bundle.

The original concept came from Red Sweater Blog: Automatic Build Sub-Versioning in Xcode. However, in my case I wanted to do the build version count between check-ins, and we are currently using GIT. (But that’s another horror story.)

Why we shouldn’t unify mobile and desktop UI frameworks.

John Gruber: Google’s Microsoft Moment

It makes no sense to me why Chrome OS isn’t based on Android. Maybe there’s a good answer to this, but Google hasn’t given it.

While I don’t understand why Google has two completely separate operating systems, one based on Davlik (a Java VM clone) and another based on Javascript (sharing more in common with the Palm WebOS platform than with Android), I do know why no-one will ever be able to successfully create a framework that unifies mobile and desktop operating systems. It’s why Apple has a separate MacOS and iPhone OS UI framework.

It’s because of the needs of each platform.

Bottom line is this: on a desktop application you can create a rich window and environment that displays everything at once. The best example of this is the Apple Mail application: in one window I see all of my mailboxes, the status of all of my mail boxes, the list of mail in my selected mail box, and the current selected message.

Mobile applications, on the other hand, have limited real estate to work with. Thus, instead of having a single window, the iPhone version of Apple Mail has a separate windows for showing accounts, showing mailboxes in an account, showing messages in a mailbox, and showing an individual message. Within a mobile version of the software we also have a notion of a “view stack”; a stack of modal views which push and pop onto a stack of views–something that has no counterpart in the desktop world.

The development model also differs: on the desktop I may have a model and controller object (from the MVC design pattern) which drives multiple views simultaneously. But on the phone, I need multiple controllers attached to the same model, each controller contains information about what was selected higher up in the view stack.

Knowing that, we can answer the question that John Gruber links: “If I make a screen two inches smaller, should I use Android instead of Chrome OS? If the keyboard works with my fingers instead of my thumbs, I should use Chrome OS and not Android?”

The answer is simple: is the screen so small that your application must be represented as a stack of views (like the iPhone mail application) or can everything relevant be placed into a single window (like the Apple mail application)? If the first answer, use the mobile version of the operating system. If the latter, use the desktop version.

Thoughts on dealing with multiple Activities and UIViewControllers

In a typical model/view/controller implementation (setting aside, of course, the debate over what MVC really is), we implement a model (which maps to a document, file, or database), a controller (which manages the views), and a collection of views, generally contained within a window.

Now this model maps nicely into the iPhone API and the Android API: the basic controller class for the iPhone is UIViewController; for Android it is android.app.Activity. And of course the view hierarchy represents the UIViews and android.view.View objects, both built-in objects and custom objects. The controller object also makes the ideal target for iPhone delegates and data objects and for the various Android interfaces which do essentially the same thing.

On the desktop, most applications are built with either a single model and a single controller. Rarely do we have multiple controllers opened onto the same model, and when this happens, more often than not the multiple controllers are multiple instances of the same class declaration: multiple text editors opened onto the same text file, for example.

Mobile devices are different. On a mobile device you can have a top level screen with one controller drill down to a separate screen (with a separate controller) which displays an individual item, which drills down to a third screen showing information about that individual item, which drills down into a fourth showing the setting for a single field.

In this example, we have four (increasingly fine grained) views into the same model: in the first screen we have a top level view; in the next, a view of an item, and so forth. The original method I was using in order to code for this particular model was to create multiple model-like objects and pass them down to individual view controllers:

Now this model tends to be somewhat informal: my top-level model is (for example) an ArrayList of Items. When it’s time to edit an item, we pass the Item as the sub-model object into the sub-control display. And when it’s time to edit some piece of the Item, we pull that piece out and pass that to the next sub-control display.

The whole process becomes messy for a variety of reasons. First, it creates a strict dependency in the flow of views; even if we use interfaces and protocols in order to isolate a control (and its respective views), we still have a lot of work to do if we want to rearrange views. Second, it creates the problem that we somehow need to pass information about which sub-item was updated back to the previous view controller. This becomes problematic since the events for UIViewController and Activity don’t map well to the notion of “saving” or “marking dirty”: there is no single event we can easily grab that consistently means “You’re going away and the view above you is becoming active.”

Android presents a few twists on this as well. First, when your Android Activity goes into the background it can be deleted from memory in a low-memory situation. That is, you can find yourself in the situation where your Activity goes away and has to be rebuilt from scratch. This implies that you must strictly separate the sub-model from the controller (as opposed to the iPhone, where you can informally combine the model and view controller into the same UIViewController class). Second, well-factored activities can be set up to be brought up by external applications: it is possible your Item editor activity can be brought up by a separate application if it knows how to launch you with the correct Intent.

It strikes me that the proper way to handle this is to have a single unified model, and instead of passing sub-models, we instead pass a small record indicating what part of the model we are working on:

The idea is that the Δ object represents a small record which indicates to the sub-controller which part of the model it is working on. This has the advantage that updates are communicated to each of the controllers which are working on this model as the object updates. This also works well on Android, as individual control/view components can disappear and re-register themselves; the delta record is passed in the Intent which created that component, so when the Activity is reconstructed the Intent can be used to put the view controls back into the correct state.

I have a simple nutrition journal application I’ve been building for the iPhone which I was going to rewrite from the ground up using this model. In future posts I’ll update the post to indicate if this works well or not.

Update to Flow Cover: don’t draw ’em if you don’t see ’em.

For those who don’t know, Flow Cover is my little implementation of the CoverFlow view by Apple, and emulates the left-right swipe view provided by CoverFlow with a new view that was written from scratch.

Alessandro Tagliati sent me the following modification to the FlowCoverView.m file:

In the -(void)draw routine (around line 410 of FlowCoverView.m), the routine draws the tiles. But it draws all of the tiles. If, instead, you just draw the visible tiles (replacing the -(void)draw routine with the following):

- (void)draw
{
	/*
	 *	Get the current aspect ratio and initialize the viewport
	 */
	
	double aspect = ((double)backingWidth)/backingHeight;
	
	glViewport(0,0,backingWidth,backingHeight);
	glDisable(GL_DEPTH_TEST);				// using painters algorithm
	
	glClearColor(0,0,0,0);
	glVertexPointer(3,GL_FLOAT,0,GVertices);
	glEnableClientState(GL_VERTEX_ARRAY);
	glTexCoordPointer(2, GL_SHORT, 0, GTextures);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	
	glEnable(GL_TEXTURE_2D);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	
	/*
	 *	Setup for clear
	 */
	
	[EAGLContext setCurrentContext:context];
	
	glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
	glClear(GL_COLOR_BUFFER_BIT);
	
	/*
	 *	Set up the basic coordinate system
	 */
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glScalef(1,aspect,1);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	/*
	 *	Change from Alesandro Tagliati :
	 *	We don't need to draw all the tiles, just the visible ones. We guess
	 *	there are 6 tiles visible; that can be adjusted by altering the 
	 *	constant
	 */
	
	int i,len = [self numTiles];
	int mid = (int)floor(offset + 0.5);
	int iStartPos = mid - VISTILES;
	if (iStartPos<0) {
		iStartPos=0;
	}
	for (i = iStartPos; i = len) {
		iEndPos = len-1;
	}
	for (i = iEndPos; i >= mid; --i) {
		[self drawTile:i atOffset:i-offset];
	}
	
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
	[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

The new lines are from the comment down to the glBindRenderbufferOES call; you can simply replace the entire routine in your code.

At the top of the FlowCoverView.m file, you’ll also need to define the constant VISTILES:

/************************************************************************/
/*																		*/
/*	Internal Layout Constants											*/
/*																		*/
/************************************************************************/

#define TEXTURESIZE			256		// width and height of texture; power of 2, 256 max
#define MAXTILES			48		// maximum allocated 256x256 tiles in cache
#define VISTILES			6		// # tiles left and right of center tile visible on screen

/*
 *	Parameters to tweak layout and animation behaviors
 */

#define SPREADIMAGE			0.1		// spread between images (screen measured from -1 to 1)
#define FLANKSPREAD			0.4		// flank spread out; this is how much an image moves way from center
#define FRICTION			10.0	// friction
#define MAXSPEED			10.0	// throttle speed to this value

Just insert the VISTILES roughly where I have it in the code snippet above.

Or you can download the zip file all over again.

Thoughts on Netbooks.

One of the things that the company I’m working for has considered is creating a Netbook version of our location-based software. So I bought a Netbook (The MSI Wind 120) in order to understand what all the fuss is about.

My observations:

(1) This is not a new product category.

To me, a new product category is a product which I interact with differently than with existing products. For example, I interact with my iPhone in a completely different way than I do with my 17″ laptop computer: I keep my iPhone in my pocket and pull it out to look thing up quickly, while my laptop gets pulled out of a briefcase and unfolded on a table.

A Netbook is a small laptop. It doesn’t fit in my pocket; I have to take it out and put it down on my lap or a table. I have to boot it up. It’s more convenient: I can use a smaller briefcase. It’ll more easily fit on the airline tray table in coach. But it’s a laptop computer.

(2) The best part about a Netbook computer is not that it is small, but that it is cheap. If you need a second computer or you cannot afford a good desktop computer, and you’re using it primarily for text editing or web browsing, a Netbook computer makes an excellent low-cost choice: I only paid $300 for mine.

(3) Other than this, the keys are cramped (making it a little harder to touch-type on), the screen is small (1024×600 pixels), making it inconvenient to use for text editing, and there is no built-in CD-ROM drive. (The Samsung SE-S084B external USB DVD-writer is around $60 and works great with the MSI Wind.) Thus, while it is an excellent low-cost choice, it’s clear it’s a low-cost choice: you are giving up a lot to save the $500-$1000 span between the 10″ laptop and a well-equipped 12″ laptop.

(4) A cheap laptop will never dethrone the iPhone in the mobile space. On the other hand the eagerness of mobile carriers to come up with something to dethrone the iPhone may force them to consider lowering the price of an all-you-can-eat data plan for laptops, which means a wireless cell card and/or built-in 3G wireless in laptops will undoubtedly be coming down the pike in the near future.

The real question, however, is will it be too little too late: a proliferation of free and cheap Wifi hotspots may make all-you-can-eat 3G wireless for laptops a terrible value proposition unless you need to surf the net out in the boondocks. (On the other hand, if you are in construction or farming, where you routinely work in the boondocks, 3G wireless for laptops will be a god-send.)

(5) A small form-factor touch-screen tablet will be a new product category if it satisfies the following requirements:

(a) Fast boot time. A touch-screen tablet needs to go from off to on in 2 seconds or less.

(b) It should be two to three times the size of the original iPhone. To get an idea of what I mean, here is a pictures showing the relative sizes of my iPhone, an HP 50g calculator, the original Kindle, the MSI Wind, and my 17″ Macbook Pro.

The iPhone is an ideal size to fit in a pocket, but once you get to the size of the HP calculator (one of the larger calculators out there), you need to put it in a backpack or a briefcase or purse. Around the size of the MSI Wind, and you need a dedicated carrying case for the device.

To me, an ideal “new product category” item would be somewhere between the size of the HP 50g calculator and the Kindle, with the Kindle being the top size for such a device.

(c) Battery capacity should be enough to allow the device to surf the ‘net and use the CPU full-boar for a minimum of 4 hours. The iPhone gets its monumental lifetime between charges from very clever power utilization: when surfing the ‘net, once a page is downloaded to your phone, the CPU is turned off. (It’s why Javascript animation execution stops after 5 seconds.) But if you write software that constantly runs and is not event-driven, especially software that uses the ‘net at the same time, the iPhone battery will drain in less than an hour.

I believe for such a small form factor touch screen device to do the trick it needs about 4 times the battery capacity of the iPhone.

Once you reach this size and have something that is “instant-on”, you now have a device that is big enough to work on where you are–and perhaps balance in one hand while you use it in another–but not so big that you need to find a table at Starbucks to pull it out. In fact, such a device would occupy the same product category space (in terms of size, form factor and how a user could interact with it) as a large calculator.

Which means one application which would be ideal for such a device would be a port of Mathematica or some other calculator software which would put the HP 50g to shame. Another application that would be ideal would be web surfing; ideally such a device would devote more disk caching than the iPhone does to web surfing. Also, vertical software for engineers, and e-book readers, would also work.

The idea here is to create a device that straddles the mid point between the iPhone “pull it out, look it up, put it away” 30 second use cycle, and the laptop “gotta find a table at Starbucks so I can pull it out of my briefcase” 1-5 hour use cycle.

And the MSI Wind (and other clamshell shaped cheap laptops) ain’t it.

Update: However, the CrunchPad very well may be the product I’m thinking about, assuming there is a way to install new software on the unit.