Urban Airship

Table of Contents

iOS

This is a developers’ guide for setting up an Urban Airship configuration for iOS apps. We will take you through the basic technical steps for configuring Apple and UA services, show you how to send your first basic push notification and rich message, and provide detailed samples and instructions for using advanced Urban Airship features.

Getting Started

In order to get started, you’ll need the following:

  1. Membership in the iOS Developer Program. If you are not an iOS developer, find out who manages the Apple Developer Program for your organization.
  2. An Urban Airship account. If you do not already have an Urban Airship ID (login credentials for Go, our online dashboard), contact Urban Airship Sales to set one up.
  3. The latest stable version of the Urban Airship iOS SDK. Note: This link will automatically download the Urban Airship SDK to your downloads folder. We’ll take you through the SDK installation process below in Setting up Urban Airship.

Apple Setup

Before you can integrate Urban Airship into your iOS apps, there are a handful of steps you must take on the Apple end of things, which require membership in the iOS Developer Program.

You will complete the following steps in the Apple Developer Member Center before your app is ready to communicate with Urban Airship:

Find Your Application

In the Apple Developer Members Center, click on Identifiers under iOS Apps and locate your application in the list.

If you haven’t registered an App ID yet, click the + symbol and fill out the form, making sure to check the Push Notifications checkbox.

When you expand the application, you will see two settings for push notifications with yellow or green status icons:

Click Settings to continue.

Note

The Settings button may be titled Edit if push notifications have been previously configured. If the Settings/Edit button is not available, you may not be the team agent or an admin. The person who originally created the developer account is your team agent and they will have to carry out the remainder of the steps in this section.

Generate Your Certificate

Note

Production vs Development Apps in Urban Airship

When you create or edit an application record on our server, you must select whether your app system is “In development, connecting to test servers,” or “In production, connecting to real push servers.” Apple treats the two servers separately, so a device token for development/sandbox will not work on production/distribution.

When building your app using a development provisioning profile, set your Urban Airship application to In development, and upload the development Push SSL certificate. To push to an app built with a distribution provisioning profile (either with a release build in Xcode, ad hoc distribution, or the iTunes App Store), use an application that is In production, and upload the production Push SSL certificate.

Because Apple treats development and production/distribution as completely separate instances, we strongly suggest making two applications in the Urban Airship web application. That way you can continue to build and develop your application even after releasing it without interrupting your users.

Warning

Do not a) submit to the App Store or b) test notifications on an ad hoc build while your app’s code is pointing to an Urban Airship app key that is set as In Development. Development apps use different tokens that, when included in a push to a production app, will fail and in many cases cause all other pushes to fail.

Always create a Production Status Urban Airship app first and make sure your application code is pointing to the production app key. For more tips on what to check before you release your app, see this support article.

  1. Choose either the Development or Production certificate option and click Create Certificate.

  2. After clicking Create Certificate, you will see the Add iOS Certificate Assistant. Follow the instructions in the assistant and then click Continue.

  3. Using the Certificate Signing request that was just created, generate the APNS Push SSL certificate.

  4. Once the Download button appears, you are ready to download. You may need to reload the page for this to update. Download the newly created certificate:

  5. Open the certificate. Opening the certificate will open Keychain Access.

In Keychain Access your certificate should be shown under “My Certificates”. If not, check “Certificates” to see if it’s located there.

Renewing Your Certificate

If you are renewing either your Development or Production Push SSL Certificate, follow the steps outlined above as if you were uploading the certificate for the first time. There is no need to revoke the previous certificate in order to make this change. There may be two production certificates at the same time, to allow you to continue using the old certificate while uploading the new one.

Export the .p12 File

You’re almost there. The final step before heading back over to the Urban Airship application is to save your signing certificate as a .p12 file.

  1. Select the certificate that was just added to Keychain Access and select File -> Export Items... from the menu. Be sure to select My Certificates under the Category menu on the lower left-hand side. If My Certificates is not highlighted, you will not be able to export the certificate as a .p12 file.

  2. When saving the file, use the Personal Information Exchange (.p12) format.

Upload Your Push Certificate to Urban Airship

Warning

Never use the same push certificate across multiple Urban Airship app keys. You should also never use the same bundle ID across multiple app keys in the same environment (development or production). Not following these instructions can result in rejected device tokens and APNs feedback processed by the wrong app key. If you need to have a third app key for ad hoc builds (which also use Distribution-type push certificates), the bundle ID should be changed so you can use a different certificate, for example: “com.yourcompany.app.adhoc”.

  1. Find your app in the Urban Airship web application and in the left-hand menu click Settings and then Services.

  2. From the list of available services to configure, navigate to Apple Push Notification Service (APNs) and click Configure.

  3. If your certificate has a password, enter it here. Then, click the Choose File button.

  4. Select the file that was saved in step 2 of Export the .p12 File.

  5. After uploading the file, make sure to click Save.

Your push certificate is now uploaded and ready for use.

Now that you’re all set up on the Apple end, it’s time to integrate Urban Airship into your iOS project. Below are the minimum steps required to configure your app(s) to talk to the Urban Airship service. We will take things from there, communicating with APNs on your behalf.

Once the Urban Airship pieces are in place, we will maintain two-way communication with Apple, sending notifications and other content on your behalf, and receiving and reporting user activity and engagement data back to you.

Setting up Urban Airship

Download & Install Our Library & Frameworks

Download and unzip the latest version of libUAirship into the same directory as your project. You should see a new directory, named Airship, containing the latest version of the libUAirship static library, along with all the public headers used by the library, as well as the AirshipKit embedded framework.

Required Libraries

The core library requires your application to link against the following Frameworks:

libUAirship-<version>.a OR AirshipKit.framework (iOS 8+ only)
CFNetwork.framework
CoreGraphics.framework
Foundation.framework
MobileCoreServices.framework
Security.framework
SystemConfiguration.framework
UIKit.framework
libz.dylib
libsqlite3.dylib
CoreTelephony.framework
CoreLocation.framework
MessageUI.framework (only required for the sample UI)
AudioToolbox.framework (only required for the sample UI)
MapKit.framework (only required for the sample UI)

New applications with iOS 8 or above as a deployment target may opt to link against AirshipKit.framework instead of libUAirship. Because AirshipKit is a true framework as opposed to a static library, applications using this framework can take advantage of features such as module-style import and automatic bridging to the Swift language. Be aware, however, that embedded frameworks are not supported on iOS 7 and below.

Create AirshipConfig.plist

The library uses a .plist configuration file named AirshipConfig.plist to manage your production and development application profiles.

  1. Create two applications within your Urban Airship account: One for development and one for production. For example:

    1. Name_of_your_app_dev
    2. Name_of_your_app_prod
  2. Create an AirshipConfig.plist file.

  3. Set the following values to the ones in your applications:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
      <key>inProduction</key>
      <false/>
      <key>developmentAppKey</key>
      <string>Your Development App Key</string>
      <key>developmentAppSecret</key>
      <string>Your Development App Secret</string>
      <key>productionAppKey</key>
      <string>Your Production App Key</string>
      <key>productionAppSecret</key>
      <string>Your Production App Secret</string>
    </dict>
    </plist>
    

    If you are using development builds and testing using the Apple sandbox set inProduction to false. For App Store and Ad-Hoc builds, set it to true. You may also allow the library to auto-detect the production mode by setting detectProvisioningMode to true.

Build Settings and Phases

The Urban Airship static library and embedded framework have slightly different setup steps.

Static Library
Header Search Paths
Ensure that your project’s Header Search Paths include the Airship directory (recursive).
Link against the static library
To link against the static library, add the libUAirship.a file to the Link Binary With Libraries section in the Build Phases tab for your target.
-ObjC Linker Flag
Add “-ObjC” linker flag to Other Linker Flags to prevent “Selector Not Recognized” runtime exceptions. The linker flag “-Wl,-force_load,$(LIB_DIRECTORY)/libUAirship-<version>.a” may be used in instances where using the -ObjC linker flag is undesirable.
Embedded Framework (iOS 8+ only)
Link against the embedded framework
To link against the embedded framework, add the AirshipKit.framework file to the Link Binary With Libraries section in the Build Phases tab for your target.
Edit runpath search paths
Existing projects will need to add the app’s Frameworks directory to the app’s runpath search paths. Failure to do this may result in an “Image not found” error at runtime.
Add a copy files phase for the framework
Existing projects will need to add a copy files phase to copy the embedded framework into the app’s Frameworks directory.

Enable Background Push

Enable background notifications that were introduced in iOS 7 by including the UIBackgroundModes key with the remote-notification value in your app’s Info.plist file. When viewing the plist in Xcode, UIBackgroundModes is displayed as Required background modes and remote-notification is displayed as App downloads content in response to push notifications.

You can also enable Background Modes and Remote notifications under the target’s Capabilities section:

Objective C Implementation

Import the required header files

At the top of your application delegate include any required headers:

#import "UAirship.h"
#import "UAConfig.h"
#import "UAPush.h"

If your application is using the embedded framework, individual header imports are no longer necessary. Instead, either import the framework’s umbrella header, or import the framework as a module. The umbrella header can be imported using angled bracket syntax:

//iOS 8+ only
#import <AirshipKit/AirshipKit.h>

To import the framework as a module:

//iOS 8+ only
@import AirshipKit;
Initialize UAirship Instance and Register for Remote Notifications

Inside your application delegate’s application:didFinishLaunchingWithOptions: method, initialize a shared UAirship instance by calling [UAirship takeOff] or [UAirship takeOff:config]. [UAirship takeOff] must be called, and return, in this method, on the main thread.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Populate AirshipConfig.plist with your app's info from https://go.urbanairship.com
    // or set runtime properties here.
    UAConfig *config = [UAConfig defaultConfig];

    // You can also programmatically override the plist values:
    // config.developmentAppKey = @"YourKey";
    // etc.

    // Call takeOff (which creates the UAirship singleton)
    [UAirship takeOff:config];
}

Set the user notification types on [UAirship push]. Sounds, alerts and badges are the default types. The library will register to receive these types of notifications as soon as user push notifications are enabled.

// Set the notification types required for the app (optional). This value defaults
// to badge, alert and sound, so it's only necessary to set it if you want
// to add or remove types.
[UAirship push].userNotificationTypes = (UIUserNotificationTypeAlert |
                                         UIUserNotificationTypeBadge |
                                         UIUserNotificationTypeSound);

User push notifications are disabled by default. To enable push later on in your application:

// User notifications will not be enabled until userPushNotificationsEnabled is
// set YES on UAPush. Once enabled, the setting will be persisted and the user
// will be prompted to allow notifications. Normally, you should wait for a more appropriate
// time to enable push to increase the likelihood that the user will accept
// notifications.
[UAirship push].userPushNotificationsEnabled = YES;

Warning

A new default behavior was introduced in SDK 6.0.0 ensuring that once user push notifications have been enabled on iOS 8+, settings may only be modified from within the iOS Settings app. Applications should link directly to the application settings.

To disable user push settings on iOS 7 or below, set userPushNotificationsEnabled to NO. If a device is running iOS 8 or higher, we recommend that the application link directly to the application’s system push settings with the UIApplicationOpenSettingsURLString URL constant.

// Open the system settings app directly to this application (on iOS 8+)
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

Register Your Device

  1. Once you have this implemented, run & compile your code.
  2. Add the application to your phone.
  3. When you open the app on your phone, it will ask for permission to send notifications. If you aren’t prompted to receive notifications, you should walk back through the steps on this page.

To make sure your device token is registered:

  1. Log in to Go
  2. On the left-hand sidebar, navigate to Audience ==> Device Tokens
  3. If your device token registered properly, it will appear in the Device Tokens listing.

Send a Test Notification

There are as many ways of using our HTTP-based API as there are programmers, but let’s get started as quickly as we can. Here’s an example using curl, a command-line tool that comes with OS X:

curl -X POST -u "<application key>:<master secret>" -H "Content-Type: application/json" -H "Accept: application/vnd.urbanairship+json; version=3;" --data '{"audience" : {"device_token" : "1111222233334444555566667777888899990000111122223333444455556666"}, "notification" : {"alert" : "Hello!"}, "device_types" : ["ios"]}' https://go.urbanairship.com/api/push/

This does a few things:

  • It sets the HTTP Basic Authentication header with the application key as the user name, and the master secret for the password.
  • It sets the Content-Type header to application/json, to tell our server you’re sending JSON.
  • It sets the data you’re sending, including the device token as the recipient.

You should receive a 200 response code, with no data in the body. This means that we accepted your request, and are processing it and sending it on to Apple!

If it worked: Congratulations!

If it didn’t work

In the iOS Provisioning Portal, click on App IDs and locate your application in the list. Next to it are two settings for push notifications with yellow or green status icons:

  1. Log in to your Urban Airship account
  2. Check your Error Console

Your Error Console provides help to debug any issues you may have as you get started. There should be reasons why the notification wasn’t received.

If you used curl to send the notification, confirm that curl is working properly by using the echo endpoint:

curl https://go.urbanairship.com/api/echo/?msg=hello

If curl is set up properly, you should receive the following response:

{
   "msg": "hello"
}

If that fails, try a different testing tool, like an HTTP Client.

If it succeeds, or if you get a different testing tool, try this to send a notification.

Check the error console in the Xcode Organizer; that can sometimes have useful information. Otherwise, go back through the process, paying close attention to:

The application ID, bundle ID, provisioning profile, and SSL certificate: All of these must point to the same identifier.

The device token: make sure you copied it correctly.

Localization for Built-In Action Buttons

Warning

This localization information only applies to Interactive Notifications. For information on localized push notifications, please see our Integration Guide.

Urban Airship provides a set of Built-in Interactive Notification types (Built-In Interactive Notification Types). These built-in action buttons are available in nine languages: English, French, German, Italian, Japanese, Portuguese, Spanish, Simplified Chinese and Traditional Chinese.

To add translations for another language, go to the Localizations section and click ‘+’ to select the language.

Next, select the UAInteractiveNotifications.strings resource file and click the Finish button.

Finally, open UAInteractiveNotifications.strings (<new language added>) in Airship/UI/Default/Common/Resources and replace the english translations with the new language.

Configuration

The library provides a number of advanced configuration features that can be controlled with the UAConfig object. UAConfig objects can either be populated from your AirshipConfig.plist file, or at runtime using its exposed properties. See the UAConfig documentation for the full list of configuration options.

Auto-detect Production Mode

By default, the library will select the app key and secret based on the inProduction setting on UAConfig, however it is also able to determine this at runtime based on the current application provisioning profile. To enable this auto-detection, set detectProvisioningMode to YES. Note that because applications running in the simulator are not signed, the library will defer to the inProduction flag when not executing on a real device.

Note

This functionality is supported only in versions 3.0.3+ of our iOS library.

Reset Rich Push Users

Rich Push user info is stored in the device keychain. This allows the user info to persist through app uninstalls and device upgrades, but this can cause problems during development if you want to test a fresh install. Expose a checkbox in the settings bundle set as a BOOL for the key “com.urbanairship.reset_keychain”. The next time the application starts, the user will automatically be reset once.

For versions of the iOS library prior to 5.0.0, users can be cleared by setting clearKeychain to YES in either AirshipConfig.plist or in the config object passed in [UAirship takeOff:(UAConfig *)config]. Please note, however, that this features clears the keychain each time that the application starts, and is deprecated as of version 5.0.0.

Automatic Integration

The Urban Airship library will automatically integrate with your app, so you do not need to implement any of the push-related UIApplicationDelegate protocol methods or pass notifications to the library. The library is able to do this by setting itself as the app delegate, intercepting messages and forwarding them to your original app delegate. If you would like to disable this behavior and implement the delegate callbacks in your own delegate, you can set automaticSetupEnabled to NO in either your AirshipConfig.plist file or on a UAConfig object passed to [UAirship takeOff:]

If you choose to disable the automatic app delegate setup, you will need to add the following code to your app delegate:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    UA_LTRACE(@"Application registered for remote notifications with device token: %@", deviceToken);
    [[UAirship push] appRegisteredForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    UA_LTRACE(@"Application did register with user notification types %ld", (unsigned long)notificationSettings.types);
    [[UAirship push] appRegisteredUserNotificationSettings];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *) error {
    UA_LERR(@"Application failed to register for remote notifications with error: %@", error);
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    UA_LINFO(@"Application received remote notification: %@", userInfo);
    [[UAirship push] appReceivedRemoteNotification:userInfo applicationState:application.applicationState];
}

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    UA_LINFO(@"Application received remote notification: %@", userInfo);
    [[UAirship push] appReceivedRemoteNotification:userInfo applicationState:application.applicationState fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())handler {
    UA_LINFO(@"Received remote notification button interaction: %@ notification: %@", identifier, userInfo);
    [[UAirship push] appReceivedActionWithIdentifier:identifier notification:userInfo applicationState:application.applicationState completionHandler:handler];
}

Logging

Log levels can be set independently for production and development modes. Set developmentLogLevel and productionLogLevel on your UAConfig.

Push

Urban Airship’s push library provides a simple interface for managing push notifications within your iOS application. Import UAirship.h and UAPush.h to begin using these features.

Badges

You can set (or reset) the badge number within your application by setting applicationIconBadgeNumber:

[UIApplication sharedApplication].applicationIconBadgeNumber = 0;

If you are using autobadge, in addition to setting the local badge number as shown above, you will need to make a device registration call to reset the server side counter:

[[UAirship push] updateRegistration];

The application’s icon badge can be manipulated with convenience methods provided by UAPush:

[[UAirship push] setBadgeNumber:1];//set to 1
[[UAirship push] resetBadge];//zero badge

A typical application will reset the badge any time a user starts the app or resumes it from the background. This can be done by making resetBadge calls from application:didFinishLaunchingWithOptions: and applicationDidBecomeActive. You may also wish to reset the badge after receiving a push when the application is running by calling reset from application:didReceiveRemoteNotification.

If your application uses Urban Airship’s autobadge feature, enable client-side autobadge tracking in application:didFinishLaunchingWithOptions: before changing the badge value:

[[UAirship push] setAutobadgeEnabled:YES];
[[UAirship push] resetBadge];//zero badge

This will ensure that the client will always sync badge changes with the server so that subsequent autobadge notifications will increment properly.

Quiet Time

// Set the quiet time from 7:30pm - 7:30am
[[UAirship push] setQuietTimeStartHour:19 startMinute:30 endHour:7 endMinute:30];

// Enable quiet time
[UAirship push].quietTimeEnabled = YES;

// Update registration
[[UAirship push] updateRegistration];

Handling Notifications

iOS handles push notifications received outside the application, but if a notification is received while the app is running, it is up to the application developer to handle it.

The sample UI includes an implementation of UAPushNotificationDelegate that handles alerts, sounds, and badges. However, if you wish to customize this behavior, you can provide your own implementation:

[UAirship push].pushNotificationDelegate = customPushDelegate;

Aliases

Aliases allow you to associate multiple devices to a single user or profile that may be associated with more than one device, e.g., an end-user’s Android phone and iPad. A device can have only one alias, and a single alias should not be associated with more than 10 devices. If it is likely that there will be more than a few devices per alias in your use case, you’d be better served by using a tag.

Set an Alias on App Start

To set an alias for a device token (Please note that the alias field can contain up to 128 bytes/128ascii characters, which can vary by language used):

- (void)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)userInfo {

    // ... your app init code

    [UAirship takeOff];

    // Sets the alias. It will be sent to the server on registration.
    NSString *yourAlias = @"Your Alias";
    [UAirship push].alias = yourAlias;
}

For setting a new alias, set the alias and update the device registration with UA.

NSString *alias = @"new_alias_string";
[UAirship push].alias = alias;

[[UAirship push] updateRegistration];
Remove Alias

To remove an alias, set the value of the alias to nil and update the device registration with UA.

[UAirship push].alias = nil;
[[UAirship push] updateRegistration];

Tags

Tags are an easy way to group device tokens. Unlike aliases, of which you can only have one (though a single alias can apply to a few devices), many tags can be applied to one or more devices. Then, a message sent to a tag will be sent out to all devices that are associated with that tag.

Tags are a good way to group device tokens by country, language, time zone or device type. These tags can be automatically generated using UATagUtils. It is good practice to minimize API calls when setting multiple tags. It’s more efficient to set them in groups.

Replace existing tags or set a new group of tags
[UAirship push].tags = @[@"one", @"two", @"three"];
[[UAirship push] updateRegistration];
Add a single tag to the current device tag list and update the server immediately
[[UAirship push] addTag:@"a_tag"];
[[UAirship push] updateRegistration];
Remove a single tag from the current device tag list and update the server immediately
[[UAirship push] removeTag:@"a_tag"];
[[UAirship push] updateRegistration];

Background Push

The library provides support for background notifications that were introduced in iOS 7. Background pushes are push notifications that can launch or resume the app in the background and fetch new content. It is highly recommended that developers enable this background mode in their applications.

To support this mode, first you must include the UIBackgroundModes key with the remote-notification value in your app’s Info.plist file. When viewing the plist in Xcode, UIBackgroundModes is displayed as Required background modes and remote-notification is displayed as App downloads content in response to push notifications.

You can also enable Background Modes and Remote notifications under the target’s Capabilities section:

Then, create a custom UAPushNotificationDelegate that implements receivedBackgroundNotification:fetchCompletionHandler:, which will perform your task when a background push is received.

Example:

- (void)receivedForegroundNotification:(NSDictionary *)notification
                fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    UA_LDEBUG(@"Received a notification while the app was already in the foreground");

    // Do something with your customData JSON, then entire notification is also available

    // Be sure to call the completion handler with a UIBackgroundFetchResult
    completionHandler(UIBackgroundFetchResultNoData);
}

- (void)launchedFromNotification:(NSDictionary *)notification
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{

    UA_LDEBUG(@"The application was launched or resumed from a notification");

    // Do something when launched via a notification

    // Be sure to call the completion handler with a UIBackgroundFetchResult
    completionHandler(UIBackgroundFetchResultNoData);
}

- (void)receivedBackgroundNotification:(NSDictionary *)notification
                fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    // Do something with the notification in the background

    // Be sure to call the completion handler with a UIBackgroundFetchResult
    completionHandler(UIBackgroundFetchResultNoData);
}

Note

If your application delegate implements application:didReceiveRemoteNotification:fetchCompletionHandler: on platforms that support background push, then your application delegate will no longer receive calls to application:didReceiveRemoteNotification:. It is still necessary to implement the non-completion handler version of the app delegate and UAPushNotificationDelegate if you are supporting older versions of iOS.

Finally, set the custom UAPushNotificationDelegate after takeOff.

Example:

[UAirship push].pushNotificationDelegate = customPushDelegate;

If background pushes are not working after following the above steps, see iOS Background Push Troubleshooting.

Interactive Notifications

Built-In Interactive Notification Types

Urban Airship provides a set of standard Interactive Notification types (See: Built-In Interactive Notification Types). It is the type that determines which buttons and corresponding labels will be available when you send a push. See the next section for where to specify that in the push payload. You control what happens when you send the push separately, by tying each button ID to a specific action.

Custom Interactive Notification Types (Categories)

In order to define a custom Interactive Notification type, you must register a new category.

Note

Urban Airship reserves category IDs prefixed with “ua_”. Any custom categories with that prefix will be dropped.

Custom UIUserNotificationCategories are supported by setting the set of categories on [UAirship push].userNotificationCategories.

Categories can be set after takeOff. After takeOff completes (i.e., application:didFinishLaunchingWithOptions: has returned), any modifications to the user notification categories will require an update to the registration settings by calling [UAirship push] updateRegistration].

Note

[UAirship push] updateRegistration] supplants [UAirship push] updateAPNSRegistration] and handles registration for both APNS and Channels.

Example:

// Define an action for the category
UIMutableUserNotificationAction *categoryAction = [[UIMutableUserNotificationAction alloc] init];
categoryAction.destructive = NO;
categoryAction.activationMode = UIUserNotificationActivationModeForeground;
categoryAction.authenticationRequired = YES;
categoryAction.title = @"Action!";
categoryAction.identifier = @"category_action";

// Define the category
UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init];
[category setActions:@[categoryAction] forContext:UIUserNotificationActionContextMinimal];
[category setActions:@[categoryAction] forContext:UIUserNotificationActionContextDefault];
category.identifier = @"custom_category";

// Set the custom categories
[UAirship push].userNotificationCategories = [NSSet setWithArray:@[category]];

// Update registration
[[UAirship push] updateRegistration];

User Notification Action Callbacks

Custom-defined Interactive Notification types can either make use of Urban Airship’s pre-defined actions, or you can write new custom action code.

If you want to bypass Urban Airship’s actions, you can can receive callbacks through either the UIApplicationDelegate or UAPushNotificationDelegate.

UIApplicationDelegate:

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier
                                                      forRemoteNotification:(NSDictionary *)userInfo
                                                          completionHandler:(void(^)())completionHandler;

UAPushNotificationDelegate:

/**
 * Called when the app is started from a user notification action button with foreground activation mode.
 *
 * @param notification The notification dictionary.
 * @param identifier The user notification action identifier.
 * @param completionHandler Should be called as soon as possible.
 */
- (void)launchedFromNotification:(NSDictionary *)notification actionIdentifier:(NSString *)identifier completionHandler:(void (^)())completionHandler;


/**
 * Called when the app is started from a user notification action button with background activation mode.
 *
 * @param notification The notification dictionary.
 * @param identifier The user notification action identifier.
 * @param completionHandler Should be called as soon as possible.
 */
- (void)receivedBackgroundNotification:(NSDictionary *)notification actionIdentifier:(NSString *)identifier completionHandler:(void (^)())completionHandler;

Actions

Urban Airship Actions provides a convenient way to automatically perform tasks by name in response to push notifications, Rich App Page interactions and JavaScript.

An action is an abstraction over a unary function, which takes an argument and performs a defined task, producing an optional result. Actions may restrict or vary the work they perform depending on the arguments they receive, which may include type introspection and runtime context.

The Urban Airship library comes with pre-made actions for common tasks such as setting/modifying tags, showing a landing page, enabling deep linking, displaying the inbox or inbox message and opening URLs out of the box. Actions can also be extended to enable custom application behaviors and engagement experiences.

In iOS, Actions are sent as part of the notification payload as top level key values, where the key is the name of the action and the value is the action’s argument. The argument can be any valid JSON value.

Actions are triggered with extra context in the form of a Situation. The different situations allows actions to determine if they should run or not, and possibly do different behavior depending on the situation.

Available Situations

Action Registry

The action registry is the central place to register actions by name. Each entry in the registry contains an action, the names that the action is registered under, a predicate that allows filtering when an action can run, and allows specifying alternative actions for different situations.

Registering an action:

[UAirship shared].actionRegistry registerAction:action names:@[@"action_name", @"action_alias"];

Looking up an action entry:

UAActionRegistryEntry *entry = [[UAActionRegistrar shared] registryEntryWithName:@"action_name"]];

Setting a predicate:

// Predicate that only allows the action to run if it was launched from a push
UAActionPredicate predicate = ^(UAActionArguments *args) {
    return (BOOL)(args.situation == UASituationLaunchedFromPush);
};

// Update the predicate
[[UAirship shared].actionRegistry updatePredicate:predicate forEntryWithName:@"action_name"];

Triggering Actions

Actions can be triggered automatically through push via our REST API or Message Composer platform. They can also be triggered automatically from a web view displaying rich message content. This interaction between web content and the Actions Framework is described in more detail in Custom HTML Templates.

It’s possible to trigger actions manually as well, but it’s more convenient and safer to run actions through the UAActionRunner. The action runner is able to run an action by a name, or run an action directly.

Example:

// Optional completion handler
UAActionCompletionHandler completionHandler = ^(UAActionResult *result) {
    UA_LDEBUG("Action finished!");
};

// Run an action by name
[UAActionRunner runActionWithName:@"action_name"
                            value:@"actionValue"
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

// Run an action directly
[UAActionRunner runAction:action
                    value:@"actionValue"
                situation:UASituationManualInvocation
        completionHandler:completionHandler];

Landing Page Action

The landing page action allows showing a rich content page when a user clicks a notification. The landing page is shown in an overlay.

Accepted Arguments
  • URL defined as a String or URL.
Default Action Names
  • landing_page_action
  • ^p
Accepted Situations
  • UASituationForegroundPush
  • UASituationLaunchedFromPush
  • UASituationBackgroundPush
  • UASituationWebViewInvocation
  • UASituationManualInvocation
  • UASituationForegroundInteractiveButton

When the landing page is invoked in situation UASituationBackgroundPush, it will only cache the landing page content in the background instead of displaying it.

Default Registry Predicate

Rejects UASituationForegroundPush and rejects UASituationBackgroundPush if the application has not been opened in the last week.

Example:

// Optional completion handler
UAActionCompletionHandler completionHandler = ^(UAActionResult *result) {
    UA_LDEBUG("Action finished!");
};

[UAActionRunner runActionWithName:@"landing_page_action"
                            value:@"http://wwww.urbanairship.com"
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

Note

Landing Page Display Default Behavior

The default behavior in the iOS SDK is to not display the Landing Page when the corresponding push notification is received while the app is in the foreground state. The logic behind this behavior is that you may not wish to interrupt or distract a user who is currently occupied with the app, only to ask them to visit a different part of the app.

If you need to display a Landing Page while the app is in the foreground state, replace the registry predicate associated with that action with one that allows foreground execution.

In the Urban Airship SDK, this relative state between what the app is doing now and how the action was invoked is known as a situation, or more properly, UASituation. Other examples of situations besides foreground state include background push and app launched from push notification.

Please see the UA Action Arguments Class Reference for more detail on the methods involved with this display behavior.

Open External URL Action

The open external URL action allows launching any URL. The action will attempt to open the url using safari.

Accepted Arguments
  • String
  • URL
Default Action Names
  • open_external_url_action
  • ^u
Accepted Situations
  • UASituationForegroundPush
  • UASituationLaunchedFromPush
  • UASituationWebViewInvocation
  • UASituationManualInvocation
  • UASituationForegroundInteractiveButton

Default Registry Predicate

Rejects UASituationForegroundPush.

Example:

// Optional completion handler
UAActionCompletionHandler completionHandler = ^(UAActionResult *result) {
    UA_LDEBUG("Action finished!");
};

[UAActionRunner runActionWithName:@"open_external_url_action"
                            value:@"http://wwww.urbanairship.com"
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

Share Action

The share action shares text using UIActivityViewController.

Accepted Arguments
  • String
Default Action Names
  • share_action
  • ^s
Accepted Situations
  • UASituationForegroundPush
  • UASituationLaunchedFromPush
  • UASituationWebViewInvocation
  • UASituationManualInvocation
  • UASituationForegroundInteractiveButton

Default Registry Predicate

Rejects UASituationForegroundPush.

Example:

// Optional completion handler
UAActionCompletionHandler completionHandler = ^(UAActionResult *result) {
    UA_LDEBUG("Action finished!");
};

[UAActionRunner runActionWithName:@"share_action"
                            value:@"Check this out!"
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

Add Tags Action

The add tags action allows adding one or more tags to the device.

Accepted Arguments
  • Single tag as a String
  • Multiple tags as an NSArray
Default Action Names
  • add_tags_action
  • ^+t
Accepted Situations
  • UASituationForegroundPush
  • UASituationLaunchedFromPush
  • UASituationWebViewInvocation
  • UASituationManualInvocation
  • UASituationForegroundInteractiveButton
  • UASituationBackgroundInteractiveButton

Example:

// Optional completion handler
UAActionCompletionHandler completionHandler = ^(UAActionResult *result) {
    UA_LDEBUG("Action finished!");
};

[UAActionRunner runActionWithName:@"add_tags_action"
                            value:@"tagOne"
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

Remove Tags Action

The remove tags action allows removing one or more tags from the device.

Accepted Arguments
  • Single tag as a String
  • Multiple tags as an NSArray
Default Action Names
  • remove_tags_action
  • ^-t
Accepted Situations
  • UASituationForegroundPush
  • UASituationLaunchedFromPush
  • UASituationWebViewInvocation
  • UASituationManualInvocation
  • UASituationForegroundInteractiveButton
  • UASituationBackgroundInteractiveButton

Example:

// Optional completion handler
UAActionCompletionHandler completionHandler = ^(UAActionResult *result) {
    UA_LDEBUG("Action finished!");
};

[UAActionRunner runActionWithName:@"remove_tags_action"
                            value:@"tagOne"
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

Open Rich Push Inbox Action

Requests the inbox be displayed. The action will call the showInboxMessage if the inbox message ID is specified and available, otherwise it will call showInbox.

Accepted Arguments
  • An optional inbox message ID as an NSString
  • nil
Default Action Names
  • open_mc_action
  • ^mc
Accepted Situations
  • UASituationForegroundPush
  • UASituationLaunchedFromPush
  • UASituationWebViewInvocation
  • UASituationManualInvocation
  • UASituationForegroundInteractiveButton

Example:

// Optional completion handler
UAActionCompletionHandler completionHandler = ^(UAActionResult *result) {
    UA_LDEBUG("Action finished!");
};

// Open the Rich Push Inbox
[UAActionRunner runActionWithName:@"open_mc_action"
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

// Open the Rich Push Message
[UAActionRunner runActionWithName:@"open_mc_action"
                            value:messageID
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

Add Custom Event Action

The custom event action creates and adds a custom events. See Custom Events for more details on Custom Events.

Accepted Arguments

  • A dictionary with the following keys
    • “event_name”: The name of the event (Required).
    • “event_value”: The value of the event.
    • “interaction_id”: The interaction ID of the event.
    • “interaction_type”: The interaction type of the event.
Default Action Names
  • add_custom_event_action
Accepted Situations
  • UASituationForegroundPush
  • UASituationLaunchedFromPush
  • UASituationWebViewInvocation
  • UASituationManualInvocation
  • UASituationForegroundInteractiveButton
  • UASituationBackgroundInteractiveButton

Default Registry Predicate Only accepts UASituationManualInvocation and UASituationWebViewInvocation situations.

Example custom event dictionary:

NSDictionary *customEventData = @{ @"event_name": @"event name",
                                   @"event_value": @(123.45) };

Running the action:

// Optional completion handler
UAActionCompletionHandler completionHandler = ^(UAActionResult *result) {
    UA_LDEBUG("Action finished!");
};

[UAActionRunner runActionWithName:@"add_custom_event_action"
                            value:customEventData
                        situation:UASituationManualInvocation
                completionHandler:completionHandler];

Custom Actions

The action framework supports any custom actions. Create an action by extending the base action class or defining an action using blocks. After takeoff, register the action. The action can be triggered the same way as built-in actions.

Note

All actions are run on the main queue. If its possible for an action to block the main queue, it should perform its work on a background queue and call the UAActionCompletionHandler when finished.

Example:

UAAction *customAction = [UAAction actionWithBlock: ^(UAActionArguments *args, UAActionCompletionHandler handler) {
    UA_LDEBUG("Action is performing with UAActionArguments: %@", args);
    handler([UAActionResult emptyResult);
}];

Register the action after takeoff:

[UAirship takeOff];
[[UAirship shared].actionRegistry registerAction:customAction name:@"custom_action"];

Reports

Our iOS client library ships with analytics support out of the box, and by default, there are no explicit preferences you need to set in order to enable reporting. The integration is handled automatically unless you set automaticSetupEnabled to NO. If so, verify you followed the steps in Automatic Integration for proper integration.

Analytics Events and Uploading

Our client library stores events in a local database and uploads them periodically in a background thread. We’ve taken great care to make sure that the database won’t grow beyond a small fixed size, so extended periods of lost connectivity are nothing to worry about. The event upload thread is woken up when new events are triggered and goes to sleep when there are no more events to process, so the impact on battery life is negligible.

Custom Events

Custom events let you track user activities and key conversions in your application, and tie them back to corresponding push messaging campaigns. Custom events requires analytics to be enabled. If disabled, any event that is added to analytics will be ignored. For a more detailed explanation on custom events and possible use cases, see the Custom Events topic guide.

Example:

UACustomEvent *event = [UACustomEvent eventWithName:@"event_name" value:@123.12];

// Record the event
[[UAirship shared].analytics addEvent:event];

Disabling Analytics

If you do not wish to include analytics and reporting in your application, in your AirshipConfig.plist file, simply set the analyticsEnabled to NO.

You can disable analytics at runtime, which will delete any locally stored events and prevent any events from uploading.

[UAirship shared].analytics.enabled = NO;

Warning

Features that depend on analytics being enabled may not work properly if it’s disabled (reports, location segmentation, region triggers, push to local time).

Rich Push

Rich Push is a service that stores and manages rich message content for your users. The message content is served directly to the user’s device and viewed via a persistent in-app inbox that we provide as a drop-in user interface.

Rich Push messages can contain any type of HTML content such as videos, polls, coupons, or any other interactive feature you choose. Rich Push messages are not subject to the same payload restrictions as push notifications because they are not delivered via APNS or GCM. However, it is simple (and recommended) to accompany a new Rich Push message with a push notification as the alert mechanism.

Since you have already integrated the client library, there are just a few additional steps required to set up the Inbox message view.

Set Up The Inbox View

If you have not already initialized a shared UAirship instance and registered for remote notifications, please refer to the Objective C Implementation section of the iOS: Getting Started section.

Note

Sample UI classes are included in the library distribution. However, you must add the UI folder to your project.

The UA iOS Sample App is available for download on our Developer Resources page.

Set up an Inbox Push Handler Delegate
Inside your application delegate’s application:didFinishLaunchingWithOptions method, provide a class that will handle UAInboxPushHandlerDelegate callbacks. These are the events that let your application know that a new message is available for viewing. In the sample application this takes the form of the app’s main view controller:
InboxSampleViewController *sampleViewController = self.viewController;

// Set the sample view controller as the Inbox push handler delegate
[UAirship inbox].pushHandler.delegate = sampleViewController;
Display Rich Push Inbox

In the provided sample UI, the main component used to display the Rich Push Inbox is the class UAInboxMessageListController. This class implements a table view that allows the user to view, mark read, and delete Rich Push messages. The simplest way to display this class is to present it as a modal view controller from the view controller that it will be shown from.

The example below demonstrates how to create and configure a message list controller, wrap it in a navigation controller, present the navigation controller modally, and set up a bar button that will dismiss the inbox when pressed:

- (UAInboxMessageListController *)buildMessageListController {
    UAInboxMessageListController *mlc = [[UAInboxMessageListController alloc] initWithNibName:@"UAInboxMessageListController" bundle:nil];
    mlc.title = @"Inbox";

    mlc.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
                                                                                         target:self
                                                                                         action:@selector(inboxDone:)];

    //the closeBlock allows for rich push messages to close the inbox after running actions
    mlc.closeBlock = ^(BOOL animated) {
        [self.userInterface hideInbox];
    };

    return mlc;
}

- (void)inboxDone:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (IBAction)inboxButtonPressed:(id)sender {
  [self presentViewControllerAnimated:YES completion:nil];
}

For a more extensive example featuring multiple user interface styles and an implementation of the UAInboxPushHandlerDelegate protocol, see the RichPushSample application.

Send a Test Rich Push

Now you should be ready to send a test Rich Push message. The easiest way to do this is by using the Rich Push Composer in the Urban Airship web application. Please refer to Rich Push Composer in our User Guide for step-by-step instructions.

Badge Updates

The value of the badge can be set in a number of ways. Most often, the number corresponds with some notion of unread or unviewed content, e.g., email messages or friend requests. The most common way to update the badge is directly through APNS, either by passing along the badge integer in the payload of a push notification, or by telling the app to adjust the value using our autobadge feature.

For Rich Push applications, you may want the badge value to represent the actual state of unread messages in the Rich Push Inbox. If so, then you need to set this behavior in the application delegate. Here is an example of how to set the current badge to the current unread message count when the application moves to inactive state:

- (void)applicationWillResignActive:(UIApplication *)application {
    UAInbox *inbox = [UAirship inbox];
    if (inbox.messageList.unreadCount >= 0) {
        [[UIApplication sharedApplication] setApplicationIconBadgeNumber:inbox.messageList.unreadCount];
    }
}

The above sample code is available in the UA sample app as well.

If you use this method then you should never include badge values in the payload of push notifications, because Rich Push will override them.

Localization

Warning

This localization information only applies to Rich Messages. For information on localized push notifications, please see our Integration Guide.

The Rich Push sample has built-in localization support and provides English resources. All Urban Airship localization strings for Rich Push are contained in a table located in the directory at Airship/UI/Default/Inbox/Resources. The provided English localization strings are contained in the en.lproj subdirectoy.

To add a new translation just copy one of the existing lproj directories parallel to en.lproj and update all of the items in UAInboxUI.strings

In-App Messaging

In-app messages are banner notifications that appear inside of your app. Aside from giving you the power to engage with users as they browse your app, they also allow you to reach opted out users in iOS 8 and above, a segment of the app audience that has previously been difficult to target.

Requirements

In-app messaging requires iOS 7+ and for Background Push to be enabled in your app’s capabilities.

A Note on Background Notifications

Without the remote notifications background mode, apps are limited to receiving silent pushes in the foreground only. On iOS 8, background notifications can be received even if the user has opted out or was never prompted. For the widest possible reach, you should encourage your users to upgrade to iOS 8.

Display

By default, in-app messages will only display a single banner on app foreground after a three-second delay. You can change this by setting the displayDelay property on [UAirship inAppMessaging]:

Adjusting the auto-display delay to five seconds:

[UAirship inAppMessaging].displayDelay = 5;

The automatic display of in-app messages can be disabled, either to block message display in response to user preferences or to manually control when and where messages should be displayed:

[UAirship inAppMessaging].isAutoDisplayEnabled = NO;

In the latter case, message display can be triggered manually so that the most recent pending message is displayed at a time more appropriate for the app:

[[UAirship inAppMessaging] displayPendingMessage];

Styling and Custom UI

Sending in-app message color overrides is supported through the composer and push API. Additional advanced styling can also be achieved by setting optional properties on the UAInAppMessaging class:

@property(nonatomic, strong) UIFont *font;
@property(nonatomic, strong) UIColor *defaultPrimaryColor;
@property(nonatomic, strong) UIColor *defaultSecondaryColor;

More comprehensive custom UI is possible by setting an optional UAInAppMessageControllerDelegate on the UAInAppMessaging object, which is used to configure details such as custom message views and animation hooks:

[UAirship inAppMessaging].messageControllerDelegate = myMessageControllerDelegate;

Required methods for the UAInAppMessageControllerDelegate protocol provide the SDK custom view and control classes at display time, configured using the data contained in the associated UAInAppMessageControllerDelegate object:

- (UIView *)viewForMessage:(UAInAppMessage *)message parentView:(UIView *)parentView;
- (UIControl *)messageView:(UIView *)messageView buttonAtIndex:(NSUInteger)index;

Optional methods allow for additional customization handling touch state (such as inverting colors when the message view is tapped) and the animation of messaging display and dismissal:

- (void)messageView:(UIView *)messageView didChangeTouchState:(BOOL)touchDown;
- (void)messageView:(UIView *)messageView animateInWithParentView:(UIView *)parentView completionHandler:(void (^)(void))completionHandler;
- (void)messageView:(UIView *)messageView animateOutWithParentView:(UIView *)parentView completionHandler:(void (^)(void))completionHandler;

Interactive Notification Compatibility Classes

In order to support interactive notification buttons on in-app messages for iOS 7, we’ve added a set of compatibility classes that mirror the functionality of apple’s user notification category and action model objects:

Use these classes instead of the corresponding UIUserNotificationCategory and UIUserNotificationAction classes if you wish to add custom interactive push buttons to in-app messages in iOS 7.

Location Targeting

The significant change service is the preferred method for acquiring data for long periods of time. If the accuracy of the significant change service is not high enough for your app’s needs, a combination of [UALocationService reportCurrentLocation] and the automaticLocationOnForegroundEnabled service can be used to add more accurate GPS data points on app foreground events. Running the standard location service for prolonged periods of time has a serious impact on battery life, and should be used wisely. On an iPhone 4S, using the full power GPS depleted 20% of the battery in 26 minutes when combined with nominal web surfing.

Make sure to include the Core Location Framework before you use our Location services.

Authorization

Before you can access the user’s location, the user must authorize your application via a location authorization prompt. For the authorization prompt to display properly, you must add the NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription keys to your application’s info.plist. To maintain iOS7 compatibility, the NSLocationUsageDescription must also be present:

Once the necessary description keys are in place, the location authorization prompt can request to allow location services only when the application is in use by setting requestAlwaysAuthorization to NO. By default, the location authorization prompt requests continuous background monitoring authorization and requestAlwaysAuthorization is set to YES:

[UAirship shared].locationService.requestAlwaysAuthorization = YES;

Check for user authorization with:

[UALocationService locationServicesEnabled];
[UALocationService locationServiceAuthorized];
[UALocationService airshipLocationServiceEnabled];

Services

After the user has given authorization, and you have enabled UA location services, you can query the user’s location with the following:

Any time a location is needed
[[[UAirship shared] locationService] reportCurrentLocation];
Starting the service
UALocationService *locationService = [[UAirship shared] locationService];
[locationService startReportingSignificantLocationChanges];

Stopping the Service

[locationService stopReportingSignificantLocationChanges];
Run in the Background

Urban Airship location services stop detecting and uploading location data when the app is sent to the background unless background location is explicitly allowed for that app. Once the background location service is allowed, location data can be detected and uploaded during the next app open when a normal Analytics event occurs. To allow UA location services in the background, set:

locationService.backgroundLocationServiceEnabled = YES;
If location services are not allowed to run in the background:
locationService.backgroundLocationServiceEnabled = NO;

Any running service will be shut down completely when an app is cleared by swiping up on that app from the Recent Apps screen whether or not backgroundLocationServiceEnabled is enabled.

Any running service that has not enabled backgroundLocationServiceEnabled will be shut down on app background (UIApplicationDidEnterBackgroundNotification) and will be automatically restarted on app foreground (UIApplicationWillEnterForegroundNotification) . Be aware of this when using the UALocationService callbacks to update UI elements with location data.

An exception to this is the single location service. The single location service, once started, will continue running as a background task until a location is retrieved or the default timeout of 30 seconds has passed. Please refer to both the Urban Airship documentation and the Apple documentation for more information:

Example

A basic combination for getting a single GPS location on app start, and then on each subsequent app foreground:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 // Override point for customization after application launch
 [window addSubview:controller.view];
 [window makeKeyAndVisible];
 [self failIfSimulator];

 // Populate AirshipConfig.plist with your app's info from https://go.urbanairship.com
 // or set runtime properties here.
 UAConfig *config = [UAConfig defaultConfig];

 // You can then programmatically override the plist values:
 // config.developmentAppKey = @"YourKey";
 // etc.

 // Call takeOff (which creates the UAirship singleton)
 [UAirship takeOff:config];

 // Set the icon badge to zero on startup (optional)
 [[UAirship push] resetBadge];

 // Set the notification types required for the app (optional). With the default value of push set to no,
 // UAPush will record the desired remote notification types, but not register for
 // push notifications as mentioned above. When push is enabled at a later time, the registration
 // will occur normally. This value defaults to badge, alert and sound, so it's only necessary to
 // set it if you want to add or remove types.
 [UAirship push].notificationTypes = (UIRemoteNotificationTypeBadge |
                                      UIRemoteNotificationTypeSound |
                                      UIRemoteNotificationTypeAlert);

  // This won't run if the user has not authorized location and you as the
  // developer have enabled location. In the code below you can see the necessary
  // code to enable location after your pitch.
  UALocationService *locationService = [[UAirship shared] locationService];
  [locationService reportCurrentLocation];
  return YES;
}

Later in your app, when you’ve made your pitch for location services, here’s how you could set up the app to automatically get a GPS location on every app foreground event.

// Enable the location service here, this value is persisted.
[UALocationService setAirshipLocationServiceEnabled:YES];
UALocationService *locationService = [[UAirship shared] locationService];
// Run this once to get the current location after the pitch
[locationService reportCurrentLocation];
// This will setup the app to get a location on every subsequent app foreground event.
// The code above will now be active, and didFinishLaunchingWithOptions:launchOptions will
// now generate a location event as well. This value is persisted.
locationService.automaticLocationOnForegroundEnabled = YES;

There is a minimum time requirement between app foreground location events which will prevent multiple updates from occurring during multitasking. The minimumTimeBetweenForegroundUpdates is accessible on the UALocationService object.

Another quick way to get location updates in your app:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Required Urban Airship push registration code (see example above)
  [UALocationService setAirshipLocationServiceEnabled:YES];
  UALocationService *locationService = [[UAirship shared] locationService];
  locationService.backgroundLocationServiceEnabled = NO;
  [locationService startReportingSignificantLocationChanges];
}

This would provide a location on each app foreground event (if it is valid), and keep the significant change provider running while the app is open. On app background, the significant change service will automatically shut down. This provides limited location data points, however, because the app would only report significant change events while the app is in the foreground. But, this would represent the leanest power consumption on the device.

Standard Location Service

For testing, it is often useful to guarantee a lot of location updates. This can be easily done by turning up the standard location service to full power.

Initializing the service
UALocationService *locationService = [[UAirship shared] locationService];
locationService.standardLocationDistanceFilter = kCLDistanceFilterNone;
locationService.standardLocationDesiredAccuracy = kCLLocationAccuracyBest;
Starting the service
[locationService startReportingStandardLocation];
Stopping the service
[locationService stopReportingStandardLocation];

You should see output of about one location per second.

Deprecated Methods

iOS 4.0 to 4.2 has a much less robust authorization system. We’ve mocked the system on later versions in such a way that we achieve almost the same functionality. However, there is no getting around that an attempt to start location has to be made before an authorization response is received. Keep this in mind when developing for older iOS versions.