Apologies for a double-post to iDevBlogADay, but I didn’t want to hit the wider audience with two straight anime/manga-related iOS blogs, and I was way behind on entries for the first few months of the year anyways.

With WWDC and presumably iOS 6 approaching, John Gruber looks for obvious gaps in iOS to fill, and in Low-Hanging Fruit, he doesn’t report many. Following on reports that Apple will switch from Google to an in-house Map provider, he writes that while controlling such an essential functionality is crucial, the switch has to be flawless:

This is a high-pressure switch for Apple. Regressions will not be acceptable. The purported whiz-bang 3D view stuff might be great, but users are going to have pitchforks and torches in hand if practical stuff like driving and walking directions are less accurate than they were with Google’s data. Keep in mind too, that Android phones ship with turn-by-turn navigation.

This was an interesting graf to me, because Gruber usually gets the details right, and this time he’s pretty far off.

Start with “users are going to have pitchforks and torches in hand if practical stuff like driving and walking directions are less accurate than they were with Google’s data.” That’s a fundamental misunderstanding of what the iOS SDK provides. Neither Map Kit, nor any other part of the SDK, provides directions. Map Kit only provides map tile images, and a “reverse geocoder” that may be able to correlate a given location to a street address or at least a political region (city, state/province, country). There’s nothing in Map Kit that knows that a yellow line is a road, a blue polygon is a lake, a dashed line is a state or country border, etc. More details in my write-up of writing Road Tip and my Bringing Your Own Maps talk from 2010, but the long-and-short is that any app that provides directions has to be getting its data from some source other than Map Kit, probably a web service hosted by Google, MapQuest, Bing, etc.

I also did a little research to see what the Android API for this stuff looks like, assuming it was easier, and was quite surprised to see that it’s not. A DrivingDirections class was apparently removed after Android 1.0, presumably due to the fact that implementing it required third-party data (TeleAtlas, NAVTEQ) that Google wasn’t in a position to redistribute for free. The suggested workarounds I’ve seen are all to either license a third-party directions API (embedded or webservice), or to make a specific request to maps.google.com and scrape the result as JSON… in other words, to use Google as the directions webservice and not worry about the terms of service. I only spent about 15 minutes looking, but it didn’t appear to me that getting directions is any easier for Android developers than it is on iOS. So while Gruber notes that “Android phones ship with turn-by-turn navigation”, that seems to be a user feature, not a developer feature.

So, on the one hand, third-party apps probably won’t change right away, because they haven’t counted on iOS for their directions anyways. But maybe that’s an opportunity: if Apple controls its own data, maybe it could offer an easy-to-use directions API, consisting of easy Objective-C calls rather than JSON or XML parsing like webservice clients have to do now.

There might be a licensing snag too: using Map Kit today means that developers are implicitly accepting the Google Maps terms of service. If iOS 6 switches providers, the terms presumably change as well, and I wonder how that would be handled. Would creating a MKMapView magically default to the new Apple maps in iOS 6 (and thereby inherit new Apple terms of service), or would developers maybe have to resubmit or add a credential to their apps to get the new maps?

And taking maps in-house has other interesting side-effects. The other day when I was out with my kids, I searched for “Arby’s” in Jackson, MI and the result appeared on the map as a “Sponsored Link” (I can’t re-create it here at home… maybe it’s only an ad when you’re physically nearby?). The money for that ad presumably goes to Google, a revenue stream that will start to dry up if Apple provides its own business location data when searching maps. We’ve also heard that Siri could hurt Google search if people start performing speech-based searches rather than keying terms into google.com via the mobile browser.

And isn’t this exactly what Google was afraid of, and why they felt the need to create Android? With iOS, Apple is in a position to disintermediate Google. And with Apple’s wrath towards Android, the company may be more interested and willing to do so than it might otherwise have been. Smooth move, Andy.

Please indulge me a Whiny Little Bitch moment. I will try to keep it short, but it will be petulant, jealous, and immature. You have been warned.

TUAW’s “RoadAhead is a different and clever nav app” talks up the new RoadAhead app, which finds upcoming services at US freeway exits. They’ll benefit from the exposure, and being free will certainly help.

But contrary to some of the reviews, the idea of an exit finder that figures out what road you’re on and what direction you’re going and only shows you upcoming exits isn’t new. That was the whole point of the Road Tip app I did a year and a half ago.

Obviously, I think that’s the way to go, and I’m glad RoadAhead does the same thing. I think it’s lazy when apps just do a radius search for this kind of thing, because that way you’ll find stuff that’s behind you, or is hopelessly far off the freeway. The idea of “finding stuff along a freeway” is a specific concept, and this app is true to it. Plus, figuring out where the road goes, winding back and forth, and dealing with things like name changes and state boundaries is a genuinely interesting problem to solve.

One point of difference is that RoadAhead can’t resist the temptation to pile on lots of icons and pinch-zoomable maps and other bling. As soon as you go down that road, the app becomes a distraction, and like so many others in this field, they explicitly say it’s unsuitable for use while driving:

One last, important thing – USING YOUR PHONE WHILE DRIVING IS A BAD IDEA (and in some states illegal). Hand your phone to your passenger and ask them to navigate. Please use good judgment when using your phone in the car.

I agree that using your phone while driving is a bad idea, but I still designed for it because I think people will do it anyways, regardless of what’s in your app description, EULA, or whatever. Road Tip uses spartan layouts, large text and buttons, and a design philosophy that everything should be accessible via one-thumb navigation. This frustrates my colleagues who say Road Tip would sell if I added various features, like the ability to save your search locations and drill deeper into them later (like remembering what’s at the exit when you pull off, so you can find stuff after you check into your hotel). My point was to keep the app as simple as possible for use while moving; once you’re off the road, you’ll be able to use the deeper functionality of other mapping apps.

So yay, I’m true to what I want my app to be… and I’m the only one who wants it like that.

The other thing is that RoadAhead is free, so I can’t figure how this app pays for itself. I decided early on that RoadTip couldn’t be ad-supported, because showing an ad to a driver would be unconscionably distracting. So I opted for a pay model.

And that brings up my other point about my exit-finding competitors. I’ve never downloaded them — I don’t want to get in a situation where I could willfully or inadvertently plagiarize them (this is why I also don’t read other people’s books on topics I’m covering) — but I’ve looked through their descriptions and legal terms, and I’ve never been able to figure out where apps like RoadAhead and iExit get their location data. That I use MapQuest is obvious; I’m contractually obligated to have my users accept the MapQuest TOS, and I have to put a “Powered by MapQuest” notice on any screens that result from their data.

So where are the other guys getting their data from? As I wrote in Bringing Your Own Maps, my research revealed that the map data providers’ terms of service for their free services always prohibited use in paid iPhone apps, either because they required callers be free and public web apps (Google Maps TOS, section 9.1.1(a)), or prohibited use based on GPS location (i.e., “present or alert an end user to individual maneuvers of a route in any way that is synchronized with the end-user’s sensor-based position along the route”, as in the Bing Maps TOS, section 2.i), or both, or something else.

This stuff is why I had to enter into commercial licensing with MapQuest (whose terms and API I liked best). Not sure what the competition is doing. Maybe they found some way to get free data legally, maybe they’re getting away with not… it’s not really my business I suppose. But if it does turn out I’m the only one playing by the rules, yeah, I’ll be a little pissed.

I keep calling them the competition, and I suppose that’s not accurate. I’m not competing at all… I’ve totally capitulated. I’m unlikely to put any further work into Road Tip, outside of possibly switching to the new I-AP subscription model that restores across devices (good for my long-time users, bad for me because it means sinking more time into this miniscule-selling app). If Ford ever followed through with opening their Sync / MyFordTouch API to third parties, I might make Road Tip work with it, but then again, I might do so just for my own use and not release it. It’s not something that I really feel like putting any further public work into.

OK, whining done. Back to your regularly scheduled blog.

A Detroit-area “Mobile Monday” group cross-posted an event to the Ann Arbor CocoaHeads group (which I attend regularly), and it’s interesting enough to make it worth my time to drive across the state twice this week. Which, in addition to traveling to Philadelpia for Voices That Matter: iPhone Developer Conference on Friday, is probably too damn much travel for one week.

[Aside: we really need a West Michigan CocoaHeads group…]

The event is going to feature a presentation from Ford on SYNC and the API they’re exposing to developers of third-party applications. At 360iDev, fellow AA CocoaHead Tom Hoag was on me to check out SYNC, and since we’ll probably have it on our next car, I would naturally be attracted to it anyways. Looking at the developer welcome page, they talk about planning to distribute apps through existing app stores, so whereas I originally thought a SYNC SDK might involve writing apps to run on the car’s CPU, maybe what it actually means is more of a protocol to be called via the iOS External Accessory framework. That would actually suit my needs much better: I’ve long wanted to voice-enable Road Tip, and being able to just connect to SYNC and let it do the voice recognition and speech synthesis is conceptually straightforward and would be very compelling. In fact, it would be more practical for the user to use SYNC’s driver-optimized microphone and the sound system’s speakers than to use in-built iOS speech frameworks (which aren’t yet available to third-party apps anyways).

But that’s actually beside the point I wanted to make, which is this: to sign up for the event, I had to join the Mobile Monday meetup group, the process for which posited this question: “Why are you interested in mobile.”

I answered: “I’m not.”

Specifically, I’m not interested in mobile, per se. Over the summer, I was talking with a high school friend of mine, Raman, who’s had a long and successful career at Microsoft. One of the things we found we both liked is the idea of having our code running where the user is. This isn’t mobility, exactly, because we both like desktop programming too. What we like is having our code executing on a device that’s where the user is, in direct interaction with the user, rather than on a server somewhere.

For the sake of coining a term, I’m calling this “user-local computing”.

I think this is an important turf to stake out becasue there’s been an almost smothering focus on the web and server-side programming for the last decade, that a lot of us feel like we’ve been left behind or overlooked. Sure, I can do server-side stuff — I’ve written servlets and SNMP traps and web services — but what I enjoy is the kind of application that’s interacting directly with a user, not looking up some database record that something else is going to present, or sending some HTML that’ll get rendered a second or two later and just sit there. Other people like that. Most people like that. In some camps, the server side is the default point of view, to the point of myopia (looking at you, Java community).

But not everything can be a webservice. Not everything should be.

There is a tangible difference to code that is executing in the user’s immediate presence, stuff that responds immediately to input, that manages resources locally. The web is getting closer — Google Instant Search is a remarkable user experience — but it still isn’t, and probably can never be, as responsive as work being done on the user’s own CPU.

There are also creative tasks that seem ill-suited to remote performance. It may well be possible to make a browser-based IDE, with source files stored on and executables built on a remote machine… but would it really be a good idea? Now let’s up the bandwidth: could you build a video editor in a browser, sending all your source media back and forth across a network connection? I’m sure someday it’ll be possible, probably soon, but I think it’ll be a long time before it’s actually a good idea.

In a way, this is a sort of retro outlook for those of us in our 40′s: the old paradigm of computing was based around creative tasks executed locally: Visicalc, WordPerfect, MacPaint, PageMaker. With the dictate that everything has to be network based, we’ve gotten more in a mindset of applications that collect and consume data from various network sources. And that’s great. But the idea of empowering your user to actually do stuff still matters, and while it may seem old-fashioned, a lot of what really matters involves clearing out the noise and distraction of the network and concentrating on doing something yourself. Notice how the new trend in text editors is to dispense with formatting, menus, toolbars, and all other distractions: it’s just you and your text. This is an ideal application of user-local computing: cut the crap, just let me focus on the here and now. “Here” being wherever I am, and whatever CPU happens to be handy.

So I’m interested in desktops, tablets, and iPhones not because of some high-falutin’ idealization of the power of mobile computing… I like them because they put my code where the user is, whether that’s at a desk, a couch, walking around, or driving in a car.

Not that I think very many people were wondering, but I do have an update to Road Tip nearly ready to go. It’s just going to take a while to get it finished and out the door.

The reason, frankly, is that it is literally not worth my time to work on it. Once I’ve paid my quarterly bills to MapQuest for their data service (without which, I wouldn’t have an app at all), my cumulative return on Road Tip is less than I make in four hours of contract programming. I can only justify time on it based on its intellectual interest, because as a professional endeavor, Road Tip has been a five-figure loss for my family’s finances once I account for expenses and the time I took to develop it.

I’m tempted to say you’ve seen the last of me as an indie iPhone developer, but you never know… I vowed not to write another computer book after the wobbling grind that was Swing Hacks, and yet I’m still at it. Best to say that indie development is now much more of a hobby in my mind, completely subordinate to contract programming and writing.

Still, I can’t help myself: I use Road Tip, and want to make it better, if only for myself. So here’s what I’ve gotten done.

  • iOS 4 foregrounding/backgrounding support – This is the big one, of course, and it’s been interesting. I handle backgrounding by opting out of location updates while backgrounded, to save the battery. This causes a number of problems at wake-up time, mostly related to the fact that any data in memory is almost certainly out of date and useless. I handle foregrounding by forcing the user back to the front screen (clearing out the presumably old data on any result page they might be on), and asking Core Location for new location data. Core Location provides timestamps in CLLocation objects, so it’s easy enough to determine if your data is old. Thing is, while I can get an updated coordinate quickly, the reported course will often be wrong (for reasons described in my earlier post on Road Tip), so I have to hold off on enabling the GUI until I have a higher level of confidence that the data supplied by Core Location is accurate.

  • HUD improvements – The “spinner” while you’re waiting for data is interminable on Edge when there’s a lot of data coming back, so I’ve added some status text to give you a better idea of what progress is actually being made. Here’s what that looks like:

  • Freestyle Favorites – The last of the features that I “always meant” to add, this feature lets you add any brand as a favorite, directly from the map screen. What this means is that you’re no longer limited to just the best-known brands from the Settings UI. You can add whatever business names you find along your way. For example, in this screenshot (taken on a family vacation last week), I could use the “make favorite” button to add the “Kahunaville” restaurant inside the Kalahari Resort in Wisconsin Dells.

    Freestyle favorites also work in tandem with the main list of favorites. If you tap “make favorite” on a brand from the canned list (like “Burger King” or “Shell”), it will just set the favorite in the main list, and you’ll see that the next time you go to the Settings app.

    BTW, the one decent critical review I got on Road Tip (as opposed to the usual anonymous 1-star haters) complained about my use of the Settings app. That was a consequence of one of my top design goals: nothing finicky in the main app. Meaning that I wanted the main app to be very “glanceable” and work with coarse gestures, not the kind of UI that requires your full attention. This is, after all, meant for use in a moving vehicle: anything distracting is bad. Heck, if iOS had a speech API, the app would be better off being completely hands-free. Anyways, scrolling through a list of brands to pick favorites is something you can do at home, and therefore can be done the Settings app (per Apple’s guidance to developers, I might add). But looking at it, I thought that putting a big “make favorite” button (which can also be un-set with a second tap) was a sufficiently coarse, non-distracting action, and potentially very handy.

  • Retina-friendly display – Despite the fact that you should be looking at Road Tip’s screen as little as possible, I did join Glyphish’s Kickstarter project so I could get Retina-display-friendly @2x icons. Kimberly Daniel of Vantage Point Creations also reworked the app icon to have a nice bezel and pre-rendered gloss

  • Purchase UI improvements – During an in-app purchase talk at CocoaHeads Ann Arbor, our group leader got confused by the long latency in pressing the “buy” button and getting the system-provided confirmation dialog. A new “purchasing…” HUD fills that gap.

All that work is done. So what’s the delay? Bugs, mostly. The backgrounding/foregrounding support has turned up some issues that either are new in iOS 4 or were always there, but never exposed because the app used to get re-launched when it was needed, rather than running indefinitely. The biggest problem at the moment is a bug where the “view all upcoming services” mode continues to get old results from whatever the first location was you searched from. Actually, it gets the freeway name right (even if you’ve since turned onto another freeway), but provides exits from the previous search results.

I’m also getting some “junk” characters in some freeway names that aren’t getting stripped out, as seen at the top of this screen.

I think it might take one full day to work through these bugs, and maybe another day to get everything set for an update submission (I have to re-write some of the help text and re-shoot some of the screenshots). So I’ll get to it at some point. I just don’t know when. Probably in the next few weeks… no promises, though.

Last weekend was the Voices That Matter: iPhone Developers Conference in Seattle, put on by Pearson, who’s publishing our Core Audio book. However, co-author Kevin Avila handled the Core Audio talk for this conference, so I took on two topics that I had fairly deep knowledge of, thanks to my work on Road Tip.

Core Location and Map Kit: Bringing Your Own Maps

This talk starts with a basic tour of Core Location’s more or less straightforward means of getting information about your current location, getting updates as the data gets better (i.e., GPS kicks in) or you move. Then we got into Map Kit and how to get map images of any given location. The sample app for this takes a list of Apple Store locations, which I converted from CSV to a plist and stuck in the app bundle, and shows you the nearest store to a given start location. Each time you hit a + button in the nav bar, it drops the next closest store as a pin on the map and re-scales the map so that all pins are visible.

This is where it gets good. Starting from a canned location at my house, the closest Apple Store is here in Grand Rapids. The next two that come up are outside Detroit (Ann Arbor and Novi). The fourth closest store is in Milwaukee. The comedy is when you see this on the map — Milwaukee is close only if you ignore the fact that going there would involve driving 100 miles straight across Lake Michigan. Since ferries across the lake are slow and expensive, and run only in Summer, you would probably drive through or around Chicago to get to Milwaukee… and go right past 7 Apple Stores in the process.

Calculating as-the-crow-flies Apple Store distances from GRR

This is a common mistake to make — I forgot to show in my slides that the apple.com retail store finder does the same thing. Still, as-the-crow-flies distance calculations, paired with map images, can be a problem. Map Kit doesn’t know anything about roads, bodies of water, geographic features, political borders, etc… all it does is serve up images, and provide a touch UI to interact with them.

The last third of the talk is about “bringing your own maps”, meaning integration with third party map data providers to get some navigational intelligence into your app. The final code sample uses the MapQuest directions web service to get actual driving distances to the first few hits, and to keep the list of locations sorted in order by driving distance. This not only keeps me from going to Milwaukee, it even smartens up the earlier results: being right on I-96, the Novi store is now my second closest result, and as it turns out, even Indianapolis is a shorter drive than going around the lake to Milwaukee.

Calculating drivable Apple Store distances from GRR

In-App Purchase: Best/Worst Thing Ever

My second talk was on In-App Purchase. In many ways, it covered the same hard-earned experience that I covered in An In-App Purchase Brain Dump. I spent a little time on both the iPhone Provisioning Portal (to set up an AppID, authorize it for I-AP, and provide enough of an app submission to create purchase objects, without actually going into the review queue), and on iTunes Connect (creating purchase products). The sample app simulated an online social game, minus the game, in which users might be able to purchase digital goods like virtual clothes for their avatar. The example offered a tabbed UI with a blank view for the game, a table of purchased objects, and a table for the store. When you tap “store”, the app collects the available products with a call to Store Kit, and tapping one of them kicks off the purchase. If the purchase goes through, the item is added to the inventory page.

Purchasing an item with I-AP

Of course, this is easier and demos better because it uses non-consumable products, which have always been the best-understood and best-supported class of I-AP products. I did weigh in against the still-broken subscriptions, and how they have to be restored to a user’s many devices, even though restoreCompletedTransactions doesn’t support subscriptions, and nothing in Store Kit gives you a key you can associate with the user to save the purchase on your own server.

Erica Sadun talked with me before this session and mentioned an interesting workaround. Get your user to purchase a non-consumable item, and persist its transactionId. When they purchase subscriptions, log the purchase and this other transactionId on your server. Then, when they restore on another device, they’ll get this non-consumable back and its transactionId, which you can then use to query your server for subscription purchases. Depending on the nature of your app, and how well you hide the clunkiness from the user, this could be a very viable workaround.

That said, I still think I-AP subscriptions suck and hope that Apple deprecates them soon.

The last part of the talk covers of doing commerce without I-AP, which is more viable than you might think. If you’re already selling digital goods from a web store, you can continue to do so, and make your iPhone app a rich client to your web-vended content. In this case, you’re already doing everything that I-AP offers, so there’s no reason to give Apple a 30% cut. For example, the various e-bookstores within Stanza don’t use I-AP — they go out to websites for O’Reilly, All Romance Books, etc., to complete the purchase. This might not be allowed for an iPhone-only app, but where the goods are available in multiple forms, it only makes sense for Apple to allow an iPhone app to be a rich client to such a store’s goods.

My final example is streaming anime: Crunchyroll sells premium content subscriptions on their website, and their free iPhone app lets you use the same login to get the same content. By contrast, The Anime Network has premium subscriptions on their website and via I-AP in their paid iPhone app, and credentials aren’t shared between the two. Worse, the iPhone app offers fewer videos for the same price. Their use of I-AP is bad for them (they’re paying Apple to process payments they’re already capable of handling), and bad for their users. WTF?

Coming next: my 360iDev slides, and the much-anticipated cleaned-up Core Audio sample code

My editor on the Core Audio book passed along my name as a potential speaker for the Voices That Matter: iPhone 2010 conference… but not on Core Audio. My co-author, Kevin Avila, has that covered. And I’ll be covering CA two weeks prior at 360iDev, so why would I want to put all that work into a talk and use it twice, when I can put lots more work into two talks. That would be too easy.

Oh, did I say two talks? I meant three. Chuck suggested I do a location/mapping talk based on my experiences developing Road Tip, and after agreeing, I noticed the schedule had a spot for an In-App Purchase talk. Foolhardy me, I said to the organizers, “hey, if you don’t have a speaker for that topic, I can take it.” So now I’ve got two talks for VTM:i.

The tricky thing is, the VTM talks are going to be pretty easy to put together, given that I’ve already written extensively about mapping and in-app purchase here on [T:c];. Heck, I did I-AP last week for Ann Arbor CocoaHeads, and I think I only swore three times.

The Core Audio talk, which comes two weeks earlier at 360iDev, will actually be the hardest to put together because the proposal and topic are still pretty nebulous — “advanced Core Audio” — and because I’ll want to pull, you know, actual advanced stuff into it. On the other hand, it’s great that there’s a “Three Core Audio Hello Worlds” earlier in the conference, covering AVAudioPlayer, OpenAL, and Audio Units to some degree, so I can elide some of the basics and get right into the hard-core.

Thing is, I now have, what, three weeks to put the hard-core together. Alas, another crunch.

Oh, and here’s a promo code for VTM:i: PHASPKR. I don’t have a code for 360iDev, but if you follow 360idev on Twitter, you might catch one flying by.

Next Page »