dr-apns

dr-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 is based jtv-apns

Install


sudo gem install dr-apns

Setup:

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 dr-apns 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

Example (Single notification):

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'})

thread = APNS.send_notification_thread(device_token, 'Hello iPhone!')
thread = APNS.send_notification_thread(device_token, :aps => {:alert => 'Hello iPhone!', :badge => 1, :sound => 'default'})
thread.join

Example (Multiple notifications):

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])

thread = APNS.send_notifications_thread([n1, n2])
thread.join

Send other info along with aps

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')

Pre-establishing connections

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

Accessing the feedback service

dr-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

Getting your iPhone’s device token

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)];	
}</p>
<p>- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    // Show the device token obtained from apple to the log
    NSLog(<code>"deviceToken: %</code>", deviceToken);
}