For mobile, it’s all native – appcelerator vs phonegap vs native

I finally took enough time to form a stronger opinion in the html5 vs. native, vs Appcelerator, vs phone gap debate and for me, I’m all in on native.  Here’s a bit of a breakdown on the different choices.

Appcelerator

  • Pros: It’s main selling point is that it allows web developers to quickly create cross platform apps using html, javascript and css.  Appcelerator will actually compile down to native code which in theory runs as fast as native code written in objective C
  • Cons: Compiling to multiple platforms is a bit of a double edged sword.  It feels like they’re constantly having to make design decisions that support the lowest common denominator between the multitude of mobile platforms.  Furthermore, inherent in this model is a bit of follow mentality.  Any time a mobile platform introduces changes, they have to catch up to provide support.  I’ve heard anecdotes about developers experiencing performance hits when using appcelerator … but I actually think I’d call BS on that.  It’s fast.

Phone Gap

  • Pros: Phone gap allows web developers to write html, css, and javascript that runs within a mobile app.  So your web devs can write code quickly across multiple platforms.
  • Cons: IMO this is a cheap solution.  Unlike appcelerator, the javascript isn’t compiled into native code.  It’s simply embedded into a UIWebView (or other webkit control for other platforms).  This has important implications that you have to understand:
  1. UIWebView is a pig and has major performance issues.  Your app is NEVER gonna be as performant as a native app.
  2. You don’t have direct access to native controls like a UINavigationController or UIPopoverController, and native resources like the photo assets on the phone.  Instead, they’ve created some admittingly pretty awesome hooks which bridge the “gap” between native controls and javascript.  But these are a bit clunky from my experience.  It’s difficult to persist application state between these controls.  They’re also playing the same game as appcelerator is here – trying to support several cross platform controls.  They’re always playing catch up, and making lowest common denominator compromises.
HTML5
I’ve heard people argue for an HTML5 version of an app instead of native, but truthfully, I’m not sure these people really know what they’re talking about.  I guess they’re suggesting an html5 website that users browse to in their phones web browser.  But that’s got incredibly obvious shortcomings – Among others, no access to native controls or assets (obviously); no ability to receive push notifications; a very different look and feel; and having zero presence that persists on the users device.
Developing native applications across platforms is more expensive, no doubt.  But without native, far too many UI and UX compromises are made in a market that’s so dominated by solutions that really nail UI and UX.

 

 

Startups should look for pain … not a nail

One thing we absolutely got correct when starting our company – we started by identifying a pain, and looked to fix it.  In particular we realized that email as a collaboration tool was broken, especially for collaborating over documents.  We set out to fix that high level pain rather than to find a problem that we could solve with our technical areas of expertise.

“Look to solve pain” is not novel advice to anyone looking to start a company, but still, all too often, you see people trying to think of startup ideas that will leverage their technical expertise.  While it obviously doesn’t’ hurt being an iPhone expert if you’re building a mobile company, there’s no reason you need to limit your options to just mobile iPhone apps.   Any programmer is capable of ramping up *enough* in an area such as mobile, web, desktop to build out a minimum viable product.  You can always bring in help latter once you’ve found product market fit.

 

 

Popular iPhone apps deliver value in 10s or less

I recently made an observation when taking inventory of the iPhone apps I have installed.

I noted that any app I use with any regularity will provide me with value in 10 seconds or less.  If it takes longer, I’d just as soon crack open the laptop and use the web/desktop version … or be distracted by some other app on my iPhone.  While there’s plenty of apps installed (at least 4 pages full), the only ones I use are Shazam, Mail, Contacts, Google Maps, Tweetie, Facebook, Weather, Showtimes …. all apps that I can get data from within 10 seconds.

It seems that the iPhone has tapped into our North American attention deficit selves.  I find myself busting out my iPhone any time I’m without stimulation … even when waiting for the traffic light to turn green.  The iPhone and it’s apps owe a lot of their success to an ability to fill the gaps in our day to day lives – it’s candy to the attention deficit.  And to me, there’s nothing better than an app that can entertain me in as little as 10 seconds.

oAuth authorization callback on the iPhone with WebView

There was a bit of chatter a while back about handling oAuth on the iPhone; in particular security balances sending a user to the website using Safari vs an embedded WebView.  Mike’s blog post discusses this so I won’t repeat, other than to say that I think either solution (webView or Safari) is open for spoofing.  An app developer could spoof an auth and grab creds in either case pretty easily … so I’ve chosen to optimize for user experience by implemented an oAuth webView for our app.

Here’s some of the relevant code for launching to an authorize website and handling the response.

* Our app uses oAuthConsumer library

* Our implimentation was against linkedin oauth which meant that I needed to pass the oauth_callback in our request token request by setting the oauth_callback parameter there rather than the authorize URL

In other words, our requestToken method looks something like the following:


OAMutableURLRequest                *request = [[[OAMutableURLRequest alloc] initWithURL: self.requestTokenURL consumer: self.consumer token:nil realm:nil signatureProvider: nil] autorelease];
 if (!request) return;
 [request setHTTPMethod: @"POST"];
 [request setParameters: [NSArray arrayWithObject: [[[OARequestParameter alloc] initWithName: @"oauth_callback" value: kLinkedInCallbackUrl] autorelease]]];
 OADataFetcher                *fetcher = [[[OADataFetcher alloc] init] autorelease];
 [fetcher fetchDataWithRequest: request delegate: self didFinishSelector: @selector(setRequestToken:withData:) didFailSelector: @selector(outhTicketFailed:data:)];

With the request token set, we’re able to pass this to the authorize url and it will return to our custom url

/*Create the request object for the linkedin URL*/


if (!_requestToken.key && _requestToken.secret) return nil;    // we need a valid request token to generate the URL

 OAMutableURLRequest            *request = [[[OAMutableURLRequest alloc] initWithURL: self.authorizeURL consumer: nil token: _requestToken realm: nil signatureProvider: nil] autorelease];

 [request setParameters: [NSArray arrayWithObject: [[[OARequestParameter alloc] initWithName: @"oauth_token" value: _requestToken.key] autorelease]]];

/*Load the webview with this request*/


[_webView loadRequest: request];

/*Check the response for a custom uri and redirect if it's set*/
- (BOOL) webView: (UIWebView *) webView shouldStartLoadWithRequest: (NSURLRequest *) request navigationType: (UIWebViewNavigationType) navigationType {
 NSData                *data = [request HTTPBody];
 char                *raw = data ? (char *) [data bytes] : "";
 NSURL* url = request.URL;

 if ([url.scheme isEqualToString:@"liconnect"]) {
 [_spinner stopAnimating];
 if ([url.resourceSpecifier isEqualToString:@"cancel"]) {
 if ([_delegate respondsToSelector:@selector(OAuthLinkedInAuthorizeViewFailed:)]) {
 [_delegate OAuthLinkedInAuthorizeViewFailed:self];
 }
 }
 else {
 [self dialogDidSucceed:url];
 }

 return NO;
 }

 if (raw && strstr(raw, "cancel=Deny")) {
 [self denied];
 return NO;
 }
 if (navigationType != UIWebViewNavigationTypeOther) _webView.alpha = 0.1;
 return YES;
}

/*Strip out the token and auth_verifier from the url*/


- (void)dialogDidSucceed:(NSURL*)url {
 NSString* q = url.query;
 NSLog(q);
 NSRange verifier_start = [q rangeOfString:@"oauth_verifier="];

 NSRange start = [q rangeOfString:@"auth_token="];
 if (start.location != NSNotFound) {
 NSRange end = [q rangeOfString:@"&"];
 NSUInteger offset = start.location+start.length;
 NSString* token = end.location == NSNotFound
 ? [q substringFromIndex:offset]
 : [q substringWithRange:NSMakeRange(offset, end.location-offset)];

 NSString* verifier = [q substringFromIndex:verifier_start.location+verifier_start.length];
 if (token&&verifier) {
 if ([_delegate respondsToSelector:@selector(requestTokenReceived:withVerifier:)]){
 [_delegate requestTokenReceived:token withVerifier:verifier];
 }
 }
 else
 {
 if ([_delegate respondsToSelector:@selector(OAuthLinkedInAuthorizeViewFailed:)]){
 [_delegate OAuthLinkedInAuthorizeViewFailed:self];
 }        }
 [self removeFromSuperview];
 }
}

You’re done.  You’ve now got your oauth_verifier and your access token all lined up to store away or make immediate calls to the api.

Our iPhone and Pre app wins top prize at Microsoft sponsored Event.

After a 54 hour coding marathon fueled mainly by pizza, caffeine, new friendships, and the enthusiasm of starting something new, our app Learn that Name won the top prize for the best app at Microsoft sponsored Startup Weekend in Redmond.

Of the many great memories from the event, the clear cut winner for me was the conclusion of the event – the presentation of the top prize. To the best of my memory the presentation went something along the lines of the following.

  • Clint Nelson (Organizer of startup weekend) – “Thanks to everyone … etc. etc.”
  • Clint -“14 of 15 teams used the Microsoft technology stack”
  • Clint –“Thanks to Microsoft, organizers, etc etc. ….”
  • General vibe in the room: YAY Microsoft!! yee of startup enablers! You rule!!!
  • Clint – “The winner of the Bizspark award given to the team winning most votes for best startup, and the one that used Microsoft platforms is …”
  • Clint – “Search Kick”
  • General vibe in room: YAY Search Kick!!! YAY Microsoft!!!!
  • Abhisheck Chitlangia (Learn that name team member) – “Wait a minute … But which team got most votes for best app?”
  • Clint – “ummm … Learn that name”
  • Me (giddy already about the impending irony) – “And which team was the one that DIDN’T use Microsoft?”
  • General feeling in room – “Huh? The team that won most votes didn’t get the award and the $5000?”
  • Clint (in a slight wisper) – “umm … Learn that name … awkward”
  • General feeling in room – Irony is setting in … the ONLY team that didn’t use the Microsoft platform was the one that won the best application … but they were essentially disqualified.
  • General feeling in room – More irony, etc etc, Learn that name team members now high fiving.

Priceless!

While the $5,000 of bizspark sponsorship would have been nice (if we’d used Microsoft technologies), the value in buzz generated from the irony as seen on techflash has already surpassed any $5,000 monetary value.

As a major footnote -
Microsoft, Bizspark, Clint, and all of the other organizers did an absolutely stellar job hosting the event. Huge props to them!! It was an amazing effort to aid the ENTIRE startup community not just those that used MS technology stack or not.
The $5000 was just the cherry on top of the overall support for startups that Microsoft provided. The award understandably could only be given to the team that used the Microsoft platform. Very smart way to drum up some interest especially in their new Azure platform.

iPhone app crash dumps

Generating Crash Reports from iPhone apps

It wasn’t obvious to me how to generate a crash dump from an iPhone add hoc deployment. It turns out that the iPhone OS creates a record of the crash event when it occurs. The next time you connect your device to iTunes, iTunes downloads the crash dump to your computer automatically.


Crash Reports on Macs

  1. Open a new finder window.

  2. Choose Go > Go to Folder.

  3. Enter ~/Library/Logs/CrashReporter/MobileDevice.

  4. Find the folder named after your device and go in there.

  5. There should be a file named after the application you’re testing.


Crash Reports from Windows

There are 2 places where windows may place your crash dump, replacing with your Windows user name shows them below.

Crash log storage on Windows Vista

C:\Users\\AppData\Roaming\Apple computer\Logs\CrashReporter/MobileDevice

Crash log storage on Windows XP

C:\Documents and Settings\\Application Data\Apple computer\Logs\CrashReporter

Once again, there is a folder named after your device’s name and a crash logs for the application you’re testing.

Blackberry storm review

I’ve been playing around with my iTouch for over a month now, appreciating it more and more every day. On Friday, I bought myself the new Blackberry storm from Verizon.

The bad:

1. The on screen keyboard isn’t effective.
While I like the tactile feedback, the keyboard is cramped. The key you are hovering over is highlighted (to allow you to make a correction before entering the key), but the keyboard is so crammed that the highlighted key is hidden underneath your finger.

2. The keyboard is often in the way and is hard to dismiss.
When using the keyboard, it often dominates the screen real estate, not allowing you to see what you are working on.

3. The UI navigation and accelerometer is sluggish.
There always seems to be a second or 2 lag before applications are opened. Furthermore, switching between landscape and portrait mode usually takes a couple seconds.

4. Commands are often 2 clicks away.
Many of the apps hide common commands away in the application menu. When sending an sms message for example, you have to open the file menu, and then select send message … instead of being able to quickly send the message with one button.

5. No wifi
I’m really puzzled by this. When data is unlimited, I don’t see the motivation to disallow users to use their own bandwidth instead of that of the Verizons

The good

1. Having a 3.2 Mpx camera is sweet!

2. GPS navigation from wireless is fast, accurate, and well designed.

3. The email application is better than the iPhone app.
Emails are consistently cached locally for quick and speedy retreival off or online, while the iPhones messages are rarely cached locally.