gs-apns is a gem for accessing the Apple Push Notification Service that allows both sending notifications and reading from apple’s feedback service. This gem extends on the prior work of James Pozdena and Paul Gebheim.
Improvements in gs-apns, by William Denniss of Geospike :
- Automatic truncation of messages to fit within the 2048 byte limit, and an exception thrown if the server payload is too big (better than dying silently)
- Truncation can truncate on word or character boundaries, and UTF-8 is fully supported (specifically, Chinese/Japanese character messages are supported)
- JSON generation uses the JSON gem directly rather than to_json which is overridden by Rails with the potential for bugs to be introduced .
- Uses Apple’s new ‘enhanced’ notification protocol allowing for an expiration date to be sent on notifications
- All 2048 of available notification payload can be used (jtv-apns & apns are currently limited to 255)
sudo gem install gs-apns
gem "gs-apns", "~> 1.0.0"
Bleeding edge:
gem 'gs-apns', :git => 'git://github.com/WilliamDenniss/APNS.git'
First, you will need to export your development/production iphone push service
certificate and key from your keychain. To do this select the private key and
certificate, and select File → Export from your keychain. By default a .p12
file will be generated containing certificate and key.
Next, run the following command to convert this .p12 file into a .pem file.
openssl pkcs12 -in cert.p12 -out cert.pem -nodes -clcerts
This pem file should be stored somewhere secure that your application can access. Next, set the configuration parameters:
################### # Hosts Config ################### # Push Notification Service: # # (default: gateway.sandbox.push.apple.com is) # Set as below for a production install APNS.host = 'gateway.push.apple.com' # (default: 2195) # APNS.port = 2195 # Feedback Service: # # (default: feedback.sandbox.push.apple.com) APNS.feedback_host = 'feedback.push.apple.com' # (default: 2196) # APNS.feedback_port = 2196 #################### # Certificate Setup #################### # Path to the .pem file created earlier APNS.pem = '/path/to/pem/file' # Password for decrypting the .pem file, if one was used APNS.pass = 'xxxx' #################### # Connection Mgmt #################### # Cache open connections when sending push notifications # this will force the gem to keep 1 connection open per # host/port pair, and reuse it when sending notifications # (default: false) # APNS.cache_connections = true ####################### # Message trunctation ####################### # soft (word break), or hard truncation (default: Truncate::TRUNCATE_METHOD_SOFT). APNS.truncate_mode = APNS::Truncate::TRUNCATE_METHOD_SOFT # for soft truncation, the maximum number of characters that will be chopped (default: 15) APNS.truncate_soft_max_chopped = 15 # if true (default: false), replaces all whitespace characters in the message with single spaces. # e.g. "\n" becomes " ", and "\n\t\n \n" becomes " ". APNS.message_clean_whitespace = false # when a message is truncated, this string is written to the end. Defaults to … (the unicode ellipsis) APNS.truncate_ellipsis_str = "\u2026" ####################### # Logging ####################### # if true (default: true), will output 1 log message for every notification in a batch, and 1 message for the batch APNS.logging = true
Then to send a push notification you can either just send a string as the alert or give it a hash for the alert, badge and sound.
device_token = '123abc456def' APNS.send_notification(device_token, 'Hello iPhone!') APNS.send_notification(device_token, :aps => {:alert => 'Hello iPhone!', :badge => 1, :sound => 'default'})
You can also send multiple notifications using the same connection to Apple:
device_token = '123abc456def' n1 = [device_token, :aps => { :alert => 'Hello...', :badge => 1, :sound => 'default' } n2 = [device_token, :aps => { :alert => '... iPhone!', :badge => 1, :sound => 'default' }] APNS.send_notifications([n1, n2])
Application-specific information can be included along with the alert by
passing it along with the “aps” key in the message hash.
APNS.send_notification(device_token, :aps => { :alert => 'Hello iPhone!', :badge => 1, :sound => 'default'}, :sent_by => 'Justin.tv')
If connection caching is enabled, you can tell the gem to establish connections before sending any notifications.
APNS.establish_notification_connection # ... if APNS.has_notification_connection? APNS.send_notification(device_token, "It works!") end
gs-apns provides a simple api to access Apple’s feedback service. Below is an example for setting the feedback time on an ActiveRecord object corresponding to a device token.
# APNS.feedback_each returns an array of Hash objects with the following keys # :feedback_on => (Time) Time Apple considers app unregistered from device # :length => (Fixnum) Length of :device_token, currently always 32 (bytes) # :device_token => (String) hex-encoded device token APNS.feedback.each do |feedback| d = RegisteredDevices.find(:first, :conditions => { :device_token = feedback.device_token }) unless d.nil? d.feedback_on = feedback.feedback_on end end
After you setup push notification for your application with Apple. You need to ask Apple for you application specific device token.
ApplicationAppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Register with apple that this app will use push notification
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];
}- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// Show the device token obtained from apple to the log
NSLog("deviceToken: %
", deviceToken);
}
Execute:
bundle exec rspec spec
To run all the rspec test-cases.