class APN::Notification

Encapsulates the logic necessary to convert an iPhone token and an array of options into a string of the format required by Apple's servers to send the notification. Much of the processing code here copied with many thanks from github.com/samsoffes/apple_push_notification/blob/master/lib/apple_push_notification.rb

APN::Notification.new's first argument is the token of the iPhone which should receive the notification. The second argument is a hash with any of :alert, :badge, and :sound keys. All three accept string arguments, while :sound can also be set to true to play the default sound installed with the application. At least one of these keys must exist. Any other keys are merged into the root of the hash payload ultimately sent to the iPhone:

APN::Notification.new(token, {:alert => 'Stuff', :custom => {:code => 23}})
# Writes this JSON to servers: {"aps" => {"alert" => "Stuff"}, "custom" => {"code" => 23}}

As a shortcut, APN::Notification.new also accepts a string as the second argument, which it converts into the alert to send. The following two lines are equivalent:

APN::Notification.new(token, 'Some Alert')
APN::Notification.new(token, {:alert => 'Some Alert'})

Constants

DATA_MAX_BYTES

Available to help clients determine before they create the notification if their message will be too large. Each iPhone Notification payload must be 2047 or fewer characters (not including the token or other push data), see Apple specs at: developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1

Attributes

options[RW]
token[RW]

Public Class Methods

new(token, opts) click to toggle source
# File lib/apn/notification.rb, line 29
def initialize(token, opts)
  @options = opts.is_a?(Hash) ? opts.symbolize_keys : {:alert => opts}
  @token = token

  raise "The maximum size allowed for a notification payload is #{DATA_MAX_BYTES} bytes." if payload_size > DATA_MAX_BYTES
end

Public Instance Methods

frame_length() click to toggle source
# File lib/apn/notification.rb, line 55
def frame_length
  packaged_frame.bytesize
end
packaged_frame() click to toggle source
# File lib/apn/notification.rb, line 59
def packaged_frame
  [token_frame, payload_frame].pack('a*a*')
end
packaged_message() click to toggle source

Converts the supplied options into the JSON needed for Apple's push notification servers. Extracts :alert, :badge, :sound and :category keys into the 'aps' hash, merges any other hash data into the root of the hash to encode and send to apple.

# File lib/apn/notification.rb, line 79
def packaged_message
  @packaged_message ||=
    begin
      opts = @options.dup
      hsh = {'aps' => {}}
      if alert = opts.delete(:alert)
        alert = alert.to_s unless alert.is_a?(Hash)
        hsh['aps']['alert'] = alert
      end
      hsh['aps']['badge'] = opts.delete(:badge).to_i if opts[:badge]
      hsh['aps']['category'] = opts.delete(:category).to_s if opts[:category]
      if sound = opts.delete(:sound)
        hsh['aps']['sound'] = sound.is_a?(TrueClass) ? 'default' : sound.to_s
      end
      if content_available = opts.delete(:content_available)
        hsh['aps']['content-available'] = 1 if [1,true].include? content_available
      end
      hsh.merge!(opts)
      Payload.new(hsh, DATA_MAX_BYTES).package
    end
end
packaged_notification() click to toggle source

Completed encoded notification, ready to send down the wire to Apple

# File lib/apn/notification.rb, line 51
def packaged_notification
  [2, frame_length, packaged_frame].pack("cl>a*")
end
packaged_token() click to toggle source

Device token, compressed and hex-ified

# File lib/apn/notification.rb, line 72
def packaged_token
  [@token.gsub(/[\s|<|>]/,'')].pack('H*')
end
payload_frame() click to toggle source
# File lib/apn/notification.rb, line 67
def payload_frame
  [2, payload_size, packaged_message].pack('cs>a*')
end
payload_size() click to toggle source
# File lib/apn/notification.rb, line 40
def payload_size
  packaged_message.bytesize
end
to_s() click to toggle source
# File lib/apn/notification.rb, line 36
def to_s
  packaged_notification
end
token_frame() click to toggle source
# File lib/apn/notification.rb, line 63
def token_frame
  [1, 32, packaged_token].pack('cs>a*')
end
valid?() click to toggle source

Ensures at least one of %w(alert badge sound) is present

# File lib/apn/notification.rb, line 45
def valid?
  return true if [:alert, :badge, :sound].any?{|key| options.keys.include?(key) }
  false
end