The simplest way to set up your app for push notifications, I think, is to use Urban Airship? and their push product:
Urban Airship Push is a scalable, easy-to-implement solution that allows you to take advantage of the rich possibilities offered by push notifications?.
They say:
We can get you up and running within a few short hours?
It’s quicker than that.
Here are the steps I followed.
- Join Urban Airship (UA)
- Provision your app for push in the developer portal, generate a new certificate signing request and download your new certificate.
- Create your app in UA and upload the certificate. UA have some instructions here.
- You might need to regenerate your provisioning profile and reinstall – just to be safe.
- Add the code to your app to register and handle push notifications. UA have some sample code.
- Choose the right provisioning profile? and build.
That’s it! When the app starts up it registers with Apple for push notifications, if that’s successful it registers with UA. You are then ready to send notifications. You can test from the UA website.
You will need to write a service to push notifications to UA. I’ll cover that in another post.
Some gotchas and notes
Make sure you choose the right provisioning profile when building otherwise you will see the error below when you run:
no valid 'aps-environment' entitlement string found for application
Make sure you use a dev provisioning profile with the dev app you set up in UA or the prod/adhoc profile with the production app. Otherwise the Apple Push service will reject the device token and UA marks the token as inactive.
If you only ever need to broadcast to all devices, you do not need to keep a list of valid devices.
If you want to be able to send to individual devices or groups (using the UA tags) then you need to keep a list of valid devices and keep the list up to date by querying the UA feedback service.
The code you need to add to your app:
#define kApplicationKey @"YOUR APP KEY" #define kApplicationSecret @"YOUR APP SECRET" - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // reset notification badge count application.applicationIconBadgeNumber = 0; //Register for notifications [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];? - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)_deviceToken { // Get a hex string from the device token with no spaces or < > self.deviceToken = [[[[_deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""] stringByReplacingOccurrencesOfString:@">" withString:@""] stringByReplacingOccurrencesOfString: @" " withString: @""]; NSLog(@"Device Token: %@", self.deviceToken); if ([application enabledRemoteNotificationTypes] == 0) { NSLog(@"Notifications are disabled for this application. Not registering with Urban Airship"); return; } // this is straight out of the UA sample code NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; NSString *UAServer = @"https://go.urbanairship.com"; NSString *urlString = [NSString stringWithFormat:@"%@%@%@/", UAServer, @"/api/device_tokens/", self.deviceToken]; NSURL *url = [NSURL URLWithString: urlString]; ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; request.requestMethod = @"PUT"; // Authenticate to the server request.username = kApplicationKey; request.password = kApplicationSecret; [request setDelegate:self]; [request setDidFinishSelector: @selector(registrationSuccessMethod:)]; // if you want to do something with the token [request setDidFailSelector: @selector(requestWentWrong:)]; [queue addOperation:request]; } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *) error { NSLog(@"Failed to register with error: %@", error); } - (void)requestWentWrong:(ASIHTTPRequest *)request { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; NSError *_error = [request error]; NSLog(@"ERROR: NSError query result: %@", _error); UIAlertView *someError = [[UIAlertView alloc] initWithTitle: @"Network error" message: NSLocalizedString( @"Error registering with notifiction server", @"Error registering with notifiction server") delegate: self cancelButtonTitle: @"OK" otherButtonTitles: nil]; [someError show]; [someError release]; }If you want to store the device tokens then:
- (void)registrationSuccessMethod:(ASIHTTPRequest *) request { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; // send to your server // however you like }The iPhoneOS handles push notifications when your app isn’t running, but what if you receive a push when your app is open? You need to implement:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { NSDictionary *apsInfo = [userInfo objectForKey:@"aps"]; NSString *alert = [apsInfo objectForKey:@"alert"]; NSString *sound = [apsInfo objectForKey:@"sound"]; NSString *badge = [apsInfo objectForKey:@"badge"]; // if you want to set the badge number application.applicationIconBadgeNumber = [[apsInfo objectForKey:@"badge"] integerValue]; // more likely you want to set it to zero application.applicationIconBadgeNumber = 0; // play sound? // show push msg UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Push Notification" message:alert delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; [alertView release]; }
Great Tutorial Thanks for this!
These two lines are giving me errors like stray
[[UIApplication sharedApplication]
11 registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
12 UIRemoteNotificationTypeSound |
13 UIRemoteNotificationTypeAlert)];?
14
15 – (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)_deviceToken {
:43: error: stray ‘357’ in program
:43: error: stray ‘273’ in program
:43: error: stray ‘277’ in program
45: error: wrong type argument to unary minus
:45: error: expected ‘;’ before ‘:’ token
total of 10 errors
Did you copy and paste? Probably got some invisible characters from the paste.
Try deleting the line entirely and retyping it.
I see and thats fixed but I also get a Unary Minus expected ;
Is this because the deviceToken wasnt declared or what
see when I try to close the method after didregister it gives me a lot of errors of how device token is not in orgnaized structure etc.
Any help.
Where and how should I declare it
In your header file:
NSString *deviceToken;
…..
@property (nonatomic, retain) NSString *deviceToken;
@Iain Munro
The unary minus thing is usually due to a missing } for the previous method.
Evening
Many thanks for the tutorial. I have been trying to get the UA Push Notification going for a while now – with no luck. Then I came across your site and thought excellent, here we go.
I got the same errors above as I did a build.
What I did was copy and paste the appropriate code from:
http://urbanairship.com/docs/apns_test_client.html
That fixed all the stray stuff, but am still getting the Unary Minus expected. I put the :
NSString *deviceToken;
…..
@property (nonatomic, retain) NSString *deviceToken;
in the header file and I still have my errors. The are two errors on the line, the Unary Minus and Expected : before : token.
So close, but so far away.
Any help would be appreciated.
Regards
Iain
@Sum
Hi Sum
Did you get this working ?
Iain