Apple does not allow apps on the iPhone to run in the background. They do this for a multitude of reasons, among them: power consumption and battery life, which in their own words “compromises the iPhone experience.” This unfortunately harpoons an entire class of applications, most prominently instant messaging applications that depend on an active network connection to keep users logged in and able to receive messages instantly.

In order to satisfy this obvious need, Apple, likely with a little help from bug reports, came up with the concept of the Push Notifications Service. Push Notifications allow Apps to report interesting information to the user when that app is not running. It does this by requiring the app author to run a server that can maintain state on behalf of the complimentary iPhone app and send messages through the APNS cloud to the user’s phone. Again, I point out that this is while the app isn’t running and has no participation in these messages. So well suited this seems to the problem of IM that Apple’s first demonstration of Push Notifications was that of an IM client.

Push Notifications are limited to 256 bytes of a JSON encoded string payload. In this 256 bytes you’re expected to fit your message, and all the options you’d like for your alert including sound and message. With english strings this may not be too bad as you can reword until you find the right phrasing and characters usually have a 1-1 mapping of number of bytes to characters used. The problem starts here when you change to asian languages like Japanese and Chinese in which a character may be represented by up to 4 bytes in UTF-8 encoding, add to this the amount of escaping that is then needed and you go from a somewhat reasonable amount to not enough to get the point across. Add to this the fact that JSON also has its own escapes for certain characters, among them “/” so a URL for example might cost you more of the payload than you expected.

Back in the Eighth grade my english teacher introduced me to a phrase that I’ve found incredibly useful in all things design related, “Close but no cigar.” It refers to a situation in which an effort is made but it falls short of the desired outcome due to among many possible reasons a lack of the finer details. The best example on the iPhone that we have to the ideal of Push Notifications is the Messages app that provides the user with SMS and for some MMS functionalities. Comparing the way the two work readily reveals the shortcomings of Push Notifications as the stopgap solution to this problem.

Push Notifications have zero interaction with the application on your device outside of expecting sounds and localized versions of alert strings in it, however when your application is launched as a result of the user acting on the push notification that he or she was sent your application is given that push notification directly to inspect. Apple’s recommendation is to use that 256 bytes and whatever you have left after adding the message, sound, and localized strings to encode meaningful app information for the application to determine what to do with this notification. Going back to the case of IM, that means that if someone sent a really long message you have to truncate that message in order to fit the tracking information in the payload that tells the App who the IM was from and that it was incomplete. Contrast this to SMS which is running in the background and when you receive an SMS there is zero wait to receive your messages since they’re already there waiting for you.

SMS Messages have stacking behavior that sometimes gets invoked, most annoyingly during a phone call. If you have multiple SMSs they all queue up alerts to displays to you one by one during a phone call. This may be the single most annoying feature of the iPhone, but it’s actually useful that it’s a handled case since in the case of the locked screen this translates to a summary notification like “3 Karl Adam” or in the case where the messages are from different people and you have several pending notifications: “3 Texts.” Push Notifications don’t have any of this behavior. Firstly they don’t stack, so if in the case of IM someone has sent you multiple messages, you’ll only see the last one with no indication that there is more than one. Push Notifications from several apps are also treated the same so if it’s only 1 IM, a new update from the NYT might be the last push notification received on the device. Push Notifications don’t control their behavior outside of the app so it’s up to Apple to fix this. A more Growl-like model might be appropriate in which there’s a registration process or at least a local entry in the applications Info.plist that gives a general description of the types of messages expected so you could at least see “3 Instant Messages” on the locked summary screen.

Now that you’re popular and received these several messages you go ahead and swipe or launch the SMS app and all your messages are waiting for you. Herein lies the key distinction that iPhone apps using Push Notifications have to deal with compared to Messages.app which runs in the background. Once an application has launched in response to push notifications it needs to connect to the network and sync with the server side status which depending on your network conditions may not be a short period of time such that you’re left waiting for what your friends have sent you. Considering that you may not know how many messages they sent it’s less than optimal to launch an application assuming the last message is the only one and forming a response for it. This could be easily solved by a small db for push notifications since the last launch of the app, mated with a larger push notification size to include the tracking information that allows the app to have the necessary state information since the last time it was launched. Then the app can quickly dirty sync its state until a full sync can be achieved but the user is not left waiting. In the case of IM this means at app launch the messages you saw in your push notifications are already waiting for you.

If you receive a push notification and read the alert then hit the close button, this is enough to indicate to the Messages app that you have read the message it wanted to inform you about so the unread messages badge is then decremented by that 1 message. Push Notifications again lack this behavior, the application gets zero notification that the left button was tapped, and while the right button can be localized to more accurately reflect the action that will be taken upon hitting this button, the left button is not available for localization or customization and will always read “Close”, or its equivalent in your language of course. So if you did fit the entire message in an alert the user would not be able to dismiss their unread badge and eventually will forget that they read the message when they go venturing into the app to find what they missed. Again with a small db of notifications you’d be able to locally determine this sort of status, since again Apple would have to provide this behavior.

Finally, the Messages app will re-notify you of messages that you’ve yet to acknowledge. You can acknowledge a Messages.app alert by viewing the message and hitting the close button, view button, or physical sleep button at the top of the device. In the case of the Messages app you can control this feature by turning it off in your preferences. In the case of push notifications this doesn’t apply, you don’t get this behavior at all.

For those interested:
rdar://7166298 – Push Notifications size should be limited to 256B as the alert, not the pay load
rdar://7114805 – Push Notifications lack a summary behavior
rdar://7114789 – Push Notifications should offer a db of the notifications since last launch
rdar://7114757 – Left Button on Push Notifications isn’t Localizable

Some people have expressed difficultly in using MPOAuth on the iPhone, so I commited a test iPhone app that merely shows how to link in MPOAuth and make use of it on the iPhone. I wrote this a while ago while testing, but have updated it now to demonstrate how to implement an MPOAuthAPIDelegate, use an inline UIWebView for user authorization, implement a custom URI handler to return control to your application and then finally make an authenticated request.

MPOAuthAPIDelegate

MPOAuthAPIDelegate allows an application to be a part of the OAuth authentication dance by providing a callback URL as well as choosing whether the user should automatically be taken to the authentication URL via the system’s default web browser.

Callback URIs

While custom callbacks URIs are a useful way for client side applications to return control to their application, many OAuth producers do not allow consumers to make use of them even for client applications. If you’re unable to get this to work it may be due to the fact that your OAuth producer does not allow it and doesn’t inform you of such. There’s also what I feel is a hacky solution for capturing url load requests and then returning the control to your application manually. This is a hack for the above problem so that you may use arbitrary domains like example.com to redirect.

Setup

In order to use MPOAuthMobile, you need to first configure it to connect to an OAuth endpoint and set your consumer key and secret in RootViewController.m lines 13 and 14.

13
14

#define kConsumerKey @"key"#define kConsumerSecret @"secret"

Among the supported OAuth endpoints in MPOAuth is twitter, so you can set http://twitter.com as the baseURL used to create your instance of MPOAuthAPI on line 39-40 and it’ll automatically do everything you need.

Usage

Once you’ve compiled the application in Xcode, it will install into the simulator or device and when it launches the OAuth dance will automatically commence by getting the unauthorized request token, and opening an inline webview for user authorization. Once you’ve provided the user credentials, the web view is animated off the display stack and the state updated again. At this stage you’re free to type in whatever method you’d like to perform on the remote endpoint. In this case I used /statuses/friends_timeline.xml to see my timeline.

Download

The code can be found in the mpaouthconnection project on google code under the MPOAuthMobile subdirectory

Steve Troughton-Smith, author of such fine iPhone apps as Speed and the jailbreak Dock enhancer Stack, has secured permission to release the game that originally made jailbreaking worthwhile, Lights Off. With new original graphics also by Adam Betts, and a rewritten code base featuring CoreAnimation snazzyness, soon we’ll all be again consumed with turning off the lights on our iPhone. While the app has not yet been submitted to the App Store you can avail yourself of news and updates about the app by visiting the website directly at lightsoffapp.com

If you’ve wanted to do anything with WebServices recently you’ve likely encountered OAuth, the open specification for client server data transmission. In a nutshell OAuth allows a desktop or web application a secure method by which to obtain user credentials for an online service without ever having to actually get the user’s username or password directly. It protects users credentials since they don’t need to give them out to multiple parties, and improves site security by giving users the tools with which to turn off the access of applications and services to their data.

Due to the proliferation of these services a common need exists to quickly be able to connect to to them without having to write yet more complicated code to do this when you just want to build your snazzy new application. Since I happen to enjoy using and writing APIs I took it upon myself to write one for OAuth for Mac and iPhone Cocoa applications. To this end, I’ve created the MPOAuthConnection set of classes that make it trivial to talk to these applications.

At the high level you merely need to tell MPOAuthAPI about the URL to your intended web service and give it your consumer key and secret and it will take care of the rest of the work of authenticating, retrieving access keys, and storing them on the user keychain on Mac OS X and iPhone*. There is a sparse delegate API for you to take part in the authentication sequence if necessary. Once authenticated you can perform method requests asynchronously or synchronously on the remote API using -performMethod:withTarget:action: or -dataForMethod: respectively.

The API is built in a layered way that allows you to, if so interested, jump in at lower levels for more direct control of the server communication and interact more directly with the classes doing the work, but so far I don’t believe this will very often be necessary. I’m using this code in a current project so it works well for me, and I’ve fixed the bugs I’ve encountered so far. I’m hoping you guys can find others, but of course if you don’t run into any that’s great too.

This code was built using the OAuth Core spec as a reference, along with the Yahoo! OAuth guide and the Google OAuth guide. It’s been tested by myself connecting to a few of the Yahoo! and Google OAuth services. It includes code excerpts from Jonathan Wight and Steve Reid for base64 encoding and HMAC-SHA1 hashing.

The entire notion that for a product like the iPhone, in-store activation would not be an issue is absurd. Everyone knew it would be a complete clusterfuck, and sure enough, it turned out to be a complete clusterfuck. One of the many screw ups that Apple didn’t discover until they were fscking up people’s plans and leaving them with no working phones is that they can’t do anything with an account that has a corporate discount or FAN number attached. If you’re one of the unlucky few to get your phone bricked you can still follow steps 2-4 of Method A to fix it. If you have a corporate discount on your current calling plan then you can not activate it on that plan or for your current number in the store regardless of how long you waited in line. There are only two methods to correct this problem and make the time you spent in line worthwhile.

Method A:

1. First you buy the phone anyway on a new plan with a new number at the Apple Store.

2. Then with your new phone you use the maps app to look up the nearest AT&T store and make your way there

3. At the AT&T store tell them to cancel your new plan, put your old SIM card in your new phone and upgrade the phone on your current plan to the iPhone 3G.

4. You now have a working phone with your current number with your corporate discount still attached.

Method B:

Buy it at the AT&T store where they can do this all correctly in the first place. Now if only they had more than 5 iPhones in each shipment…