Cocoa in the Shell

Changes in the APNS Binary Interface and Notification Format

I don’t know when, but the APNS documentation for The Binary Interface and Notification Format was updated, well probably along with iOS 7. Fact is, I stumbled upon it this week and saw that the good olds ways were now “Legacy”. I didn’t find much informations about it on the net and the WWDC 2013 videos don’t talk about it, so I had to take a look at it.

So, before there was two formats to send push notifications through the binary interface, let’s take a quick look to remember.

I - Simple Notification format

This is the original format introduced along with the push notifications on iOS 3.0.

Simple notification format (© Apple)
Simple notification format (© Apple)
  1. Command: 1 byte, always 0.
  2. Token length: 2 bytes, size of the device token = 32.
  3. Token: 32 bytes, device token.
  4. Payload length: 2 bytes, size of the payload, which can no exceed 256 bytes.
  5. Payload: <= 256 bytes, JSON payload.

Pretty straightforward, not much to say here, this has been along for a very long time and most of the open sources code we find on the net use this format.

II - Enhanced Notification Format

This one came later and added two fields to the binary interface and the ability to receive a response from the APNS server.

Enhanced notification format (© Apple)
Enhanced notification format (© Apple)
  1. Command: 1 byte, always 1.
  2. Identifier: 4 bytes, a value to identify the notification.
  3. Expiry: 4 bytes, UNIX epoch date in seconds to identify when the notification should expires on the APNS server, 0 tells the server to discard it once it is sent.
  4. Token length: 2 bytes, size of the device token = 32.
  5. Token: 32 bytes, device token.
  6. Payload length: 2 bytes, size of the payload, which can no exceed 256 bytes.
  7. Payload: <= 256 bytes, JSON payload.

What’s good is the identifier field, as the name implies it allows to identify a single notification, and will be useful when the server sends us a response (see below). A good idea is to increment this identifier for each notification sent.

A response looks like this :

APNS response (© Apple)
APNS response (© Apple)
  1. Command: 1 byte, always 8.
  2. Status: 1 byte, Status code, indicate the error (see the documentation for the meaning).
  3. Identifier: 4 bytes, This refers to the identifier of the notification (2nd field).

That was way better than the simple format, because thanks to the identifier returned by the server we could know what went wrong for which notification.
The identifier was the last one for which a notification was successfully sent, so we could assume that all the notifications with an identifier greater than this one were not sent, and so we could send them again.

III - The new format

It changed quite a bit.

New notification format (© Apple)
New notification format (© Apple)
  1. Command: 1 byte, always 2.
  2. Frame length: 4 bytes, size of the frame.
  3. Frame data: Variable, frame.

Now as you can see, a frame is composed of severals items, most likely five. And an item is composed of three fields.

  1. Item ID: 1 byte, identifier of the item.
  2. Item data length: 2 bytes, size of the item data.
  3. Item data: Variable, value of this item.

The list of item identifiers (1 to 5) is as follow :

  1. Device token: 32 bytes, the device token.
  2. Payload: <= 256 bytes, The JSON payload.
  3. Notification identifier: 4 bytes, a value to identify the notification.
  4. Expiration date: 4 bytes, UNIX epoch date in seconds to identify when the notification should expires on the APNS server, 0 tells the server to discard it once it is sent.
  5. Priority: The notification’s priority. 10 = send immediately, 5 = send when it’s best for the device battery.

The new thing here is the priority field, which allows us to decide if we want to send the notification now, just like before, or at later time, but without any precise control.

The response is the same as the Enhanced format.

The JSON payload is pretty much the same since the beginning, there’s just a new field called content-available used for background content download for Newsstand apps.

With that, I updated MacGPusher on github to handle this new format.

And… I completed my objective of writing at least a blog post this year, sugoi.

Tags: