iPhone Programming: Push notifications, Part 4 12 Ways To Conserve Your iPhone Battery Power
Jun 30

xcode_logoThis is part 5 of the Push notification tutorial.  Here you can find part 4.

This chapter describes the tasks that a iPhone or iPod touch application should (or might) do to implement the client side of the remote-notifications feature. Because the client-side API refers to these notifications as “remote notifications,” that terminology is used in this chapter.

Note: A client application should always communicate with its provider asynchronously or on a secondary thread.

Preparing Custom Alert Sounds

Providers can specify custom sounds that iPhone OS plays when it receives a remote notification for an application. The sound files must be in the main bundle of the client application.

Because custom alert sounds are played by the iPhone OS system-sound facility, they must be in one of the following audio data formats:

  • linear PCM
  • MA4 (IMA/ADPCM)
  • µLaw
  • aLaw

You can package the audio data in an aiff, wav, or caf file. Then, in Xcode, add the sound file to your project as a nonlocalized resource of the application bundle.

You may use the afconvert tool to convert sounds. For example, to convert the 16-bit linear PCM system sound Submarine.aiff to IMA4 audio in a CAF file, use the following command in the Terminal application:

afconvert /System/Library/Sounds/Submarine.aiff ~/Desktop/sub.caf -d ima4 -f caff -v 

You can inspect a sound to determine its data format by opening it in QuickTime Player and choosing Show Movie Inspector from the Movie menu.

Registering for Remote Notifications

An application must register with Apple Push Notification Service for iPhone OS to receive remote notifications sent by the application’s provider. Registration has three stages:

  1. The application calls the registerForRemoteNotificationTypes: method of UIApplication.
  2. It implements the application:didRegisterForRemoteNotificationsWithDeviceToken: method of UIApplicationDelegate to receive the device token.
  3. It passes the device token to its provider as a non-object, binary value.

What happens between the application, the device, Apple Push Notification Service, and the provider during this sequence is illustrated by Figure 2-3 in “Token Generation and Dispersal.”

An application should register every time it launches and give its provider the current token. It calls registerForRemoteNotificationTypes: to kick off the registration process. The parameter of this method takes a UIRemoteNotificationType bit mask that specifies the initial types of notifications that the application wishes to receive—for example, icon-badging and sounds, but not alert messages. Users can thereafter modify the enabled notification types in the Notifications preference of the Settings application, and you can retrieve the currently enabled notification types by calling the enabledRemoteNotificationTypes method. iPhone OS does not badge icons, display alert messages, or play alert sounds if any of these notifications types are not enabled, even if they are specified in the notification payload.

If registration is successful, APNs returns a device token to the device and iPhone OS passes the token to the application delegate in the application:didRegisterForRemoteNotificationsWithDeviceToken: method. The application should connect with its provider and pass it this token, encoded in binary format. If there is a problem in obtaining the token, iPhone OS informs the delegate by calling the application:didFailToRegisterForRemoteNotificationsWithError: method. The NSError object passed into this method clearly describes the cause of the error.

Note: By requesting the device token and passing it to the provider every time your application launches, you help to ensure that the provider has the current token for the device. If a user restores a backup to a device other than the one that the backup was created for (for example, the user migrates data to a new device), he or she must launch the application at least once for it to receive notifications again. If the user restores backup data to a new device or reinstalls the operating system, the device token changes. Moreover, never cache a device token and give that to your provider; always get the token from the system whenever you need it.

It is acceptable to call registerForRemoteNotificationTypes: every time the application launches because iPhone OS knows if your application is already registered. If it is, iPhone OS passes the device token to the delegate immediately without setting notification types or incurring any additional overhead.

Listing 5-1 gives a simple example of how you might register for remote notifications. (SendProviderDeviceToken is a hypothetical method defined by the client in which it connects with its provider and passes it the device token.)

Listing 5-1 Registering for remote notifications

- (void)applicationDidFinishLaunching:(UIApplication *)app { 
   // other setup tasks here.... 
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]; 
} 
  
// Delegation methods 
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)
devToken {
    const void *devTokenBytes = [devToken bytes];
    self.registered = YES;
    [self sendProviderDeviceToken:devTokenBytes]; // custom method
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
    NSLog(@"Error in registration. Error: %@", err);
}

Passing the Provider the Current Language Preference

If an application doesn’t use the loc-key and loc-args properties of the aps dictionary for client-side fetching of localized alert messages, the provider needs to localize the text of alert messages it puts in the notification payload. To do this, however, the provider needs to know the language that the device user has selected as the preferred language. (The user sets this preference in the General > International > Language view of the Settings application.) The client application should send its provider an identifier of the preferred language; this could be a canonicalized IETF BCP 47 language identifier such as “en” or “fr”.

Note: For more information about the loc-key and loc-args properties and client-side message localizations, see “The Notification Payload.”

Listing 5-2 illustrates a technique for obtaining the currently selected language and communicating it to the provider. In iPhone OS, the array returned by the preferredLanguages of NSLocale contains one object: an NSString object encapsulating the language code identifying the preferred language. The UTF8String coverts the string object to a C string encoded as UTF8.

Listing 5-2 Getting the current supported language and sending it to the provider

NSString *preferredLang = [[NSLocale preferredLanguages] objectAtIndex:0];
const char *langStr = [preferredLang UTF8String];
[self sendProviderCurrentLanguage:langStr]; // custom method
}

The application might send its provider the preferred language every time the user changes something in the current locale. To do this, you can listen for the notification named NSCurrentLocaleDidChangeNotification and, in your notification-handling method, get the code identifying the preferred language and send that to your provider.

If the preferred language is not one the application supports, the provider should localize the message text in a widely spoken fallback language such as English or Spanish.

Handling Remote Notifications

iPhone and iPod touch applications that depend on their providers for data typically have one thing in common. Just after they launch, they connect with their providers and fetch the waiting data, often animating a progress indicator while data is being downloaded. They also reset the badge number associated with the application icon. Listing 5-3 gives a simple illustration of this procedure, which the delegate implements in the applicationDidFinishLaunching: method.

Listing 5-3 Downloading data from a provider

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    // other setup tasks here....
    [self startDownloadingDataFromProvider];  // custom method
    application.applicationIconBadgeNumber = 0;
    // ...
}

This procedure suffices for most remote notifications, which arrive at the device when the application isn’t running. iPhone OS badges the application icon, plays a sound, or presents an alert message. The user responds by tapping the application to launch it. Or, in the case of the alert message, the user taps the View button, which results in the launch of the application.

However, there are two situations where applicationDidFinishLaunching: is not a suitable implementation site:

  • The application is running when the notification arrives.
  • The notification payload contains custom data that the application can use.

In the first case, where the application is running when iPhone OS receives a remote notification, you should implement the application:didReceiveRemoteNotification: method of UIApplicationDelegate. if you want to download the data immediately. After downloading, be sure to remove the badge from the application icon. (If your application frequently checks with its provider for new data, implementing this method might not be necessary.)

In the second case, the notification payload contains custom data that the application can use, for example, to provide context when setting up the initial user interface. For both of these cases, you may implement both application:didReceiveRemoteNotification: (for when the application is running when the notification arrives) and application:didFinishLaunchingWithOptions: (for when the application isn’t running). For both methods, iPhone OS passes in the payload dictionary when it calls them. In addition to downloading data from the provider and removing the application-icon badge, the delegate can fetch any custom properties from the dictionary and apply them as necessary.

Important: As noted elsewhere in this document, you should never define custom properties in the notification payload for the purpose of transporting customer data or any other sensitive data. Delivery of remote notifications is not guaranteed. One example of an appropriate usage for a custom payload property is a string identifying an email account from which messages are downloaded to an email client; the application can incorporate this string in its download user-interface. Another example of custom payload property is a timestamp for when the provider first sent the notification; the client application can use this value to gauge how old the notification is.

credit: apple.com


Spread the word:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Reddit
  • Technorati
  • Tumblr
  • Twitter

One Response to “iPhone Programming: Push notifications, Part 5”

  1. Dhaval says:

    Please, tell me the procedure for connecting client application to the provider and then pass Device Token to it.

Leave a Reply

preload preload preload