Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Support iOS 8's new actionable notifications #31

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions MIT-LICENSE
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Copyright (c) 2009 James Pozdena

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
Expand All @@ -8,10 +8,10 @@ copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Expand Down
20 changes: 10 additions & 10 deletions README.textile
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ After you have your .pem file. Set what host, port, certificate file location on

<pre>
<code>
APNS.host = 'gateway.push.apple.com'
APNS.host = 'gateway.push.apple.com'
# gateway.sandbox.push.apple.com is default

APNS.pem = '/path/to/pem/file'
# this is the file you just created
APNS.port = 2195

APNS.port = 2195
# this is also the default. Shouldn't ever have to set this, but just in case Apple goes crazy, you can.
</code>
</pre>
Expand Down Expand Up @@ -58,7 +58,7 @@ You can also send multiple notifications using the same connection to Apple:
n1 = APNS::Notification.new(device_token, 'Hello iPhone!' )

n2 = APNS::Notification.new(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')

APNS.send_notifications([n1, n2])
</code>
</pre>
Expand Down Expand Up @@ -92,17 +92,17 @@ h3. ApplicationAppDelegate.m

<pre>
<code>
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
// Register with apple that this app will use push notification
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert |
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];

// Your app startup logic...
return YES;
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
// Convert the binary data token into an NSString (see below for the implementation of this function)
NSString *deviceTokenAsString = stringFromDeviceTokenData(deviceToken);
Expand All @@ -122,11 +122,11 @@ This snippet comes from "this stackoverflow post's anwser":http://stackoverflow.
{
const char *data = [deviceToken bytes];
NSMutableString* token = [NSMutableString string];

for (int i = 0; i < [deviceToken length]; i++) {
[token appendFormat:@"%02.2hhX", data[i]];
}

return [[token copy] autorelease];
}
</code>
Expand Down
14 changes: 7 additions & 7 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ require 'rake/gempackagetask'
require 'rubygems/specification'
require 'date'
require 'spec/rake/spectask'

GEM = 'apns'
GEM_NAME = 'apns'
GEM_VERSION = '0.9.0'
AUTHORS = ['James Pozdena']
EMAIL = "[email protected]"
HOMEPAGE = "http://github.com/jpoz/apns"
SUMMARY = "Simple Apple push notification service gem"

spec = Gem::Specification.new do |s|
s.name = GEM
s.version = GEM_VERSION
Expand All @@ -27,24 +27,24 @@ spec = Gem::Specification.new do |s|
s.autorequire = GEM
s.files = %w(MIT-LICENSE README.textile Rakefile) + Dir.glob("{lib}/**/*")
end

task :default => :spec

desc "Run specs"
Spec::Rake::SpecTask.new do |t|
t.spec_files = FileList['spec/**/*_spec.rb']
t.spec_opts = %w(-fs --color)
end

Rake::GemPackageTask.new(spec) do |pkg|
pkg.gem_spec = spec
end

desc "install the gem locally"
task :install => [:package] do
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
end

desc "create a gemspec file"
task :make_spec do
File.open("#{GEM}.gemspec", "w") do |file|
Expand Down
2 changes: 1 addition & 1 deletion lib/apns/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def self.packed_nofications(notifications)

notifications.each do |notification|
# Each notification frame consists of
# 1. (e.g. protocol version) 2 (unsigned char [1 byte])
# 1. (e.g. protocol version) 2 (unsigned char [1 byte])
# 2. size of the full frame (unsigend int [4 byte], big endian)
pn = notification.packaged_notification
bytes << ([2, pn.bytesize].pack('CN') + pn)
Expand Down
16 changes: 9 additions & 7 deletions lib/apns/notification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ module APNS
require 'openssl'

class Notification
attr_accessor :device_token, :alert, :badge, :sound, :other, :priority
attr_accessor :device_token, :alert, :badge, :sound, :category, :other, :priority
attr_accessor :message_identifier, :expiration_date
attr_accessor :content_available

def initialize(device_token, message)
self.device_token = device_token
if message.is_a?(Hash)
self.alert = message[:alert]
self.badge = message[:badge]
self.sound = message[:sound]
self.category = message[:category]
self.other = message[:other]
self.message_identifier = message[:message_identifier]
self.content_available = !message[:content_available].nil?
Expand All @@ -29,7 +30,7 @@ def initialize(device_token, message)

self.message_identifier ||= OpenSSL::Random.random_bytes(4)
end

def packaged_notification
pt = self.packaged_token
pm = self.packaged_message
Expand All @@ -47,23 +48,24 @@ def packaged_notification
data << [3, pi.bytesize, pi].pack("CnA*")
data << [4, 4, pe].pack("CnN")
data << [5, 1, pr].pack("CnC")

data
end

def packaged_token
[device_token.gsub(/[\s|<|>]/,'')].pack('H*')
end

def packaged_message
aps = {'aps'=> {} }
aps['aps']['alert'] = self.alert if self.alert
aps['aps']['badge'] = self.badge if self.badge
aps['aps']['sound'] = self.sound if self.sound
aps['aps']['category'] = self.category if self.category
aps['aps']['content-available'] = 1 if self.content_available

aps.merge!(self.other) if self.other
aps.to_json
end
end
end
end
21 changes: 13 additions & 8 deletions spec/apns/notification_spec.rb
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
require File.dirname(__FILE__) + '/../spec_helper'

describe APNS::Notification do

it "should take a string as the message" do
n = APNS::Notification.new('device_token', 'Hello')
n.alert.should == 'Hello'
end

it "should take a hash as the message" do
n = APNS::Notification.new('device_token', {:alert => 'Hello iPhone', :badge => 3})
n.alert.should == "Hello iPhone"
n.badge.should == 3
end

it "should have a priority if content_availible is set" do
n = APNS::Notification.new('device_token', {:content_available => true})
n.content_available.should be_true
n.priority.should eql(5)
end

describe '#packaged_message' do

it "should return JSON with notification information" do
n = APNS::Notification.new('device_token', {:alert => 'Hello iPhone', :badge => 3, :sound => 'awesome.caf'})
n.packaged_message.should == "{\"aps\":{\"alert\":\"Hello iPhone\",\"badge\":3,\"sound\":\"awesome.caf\"}}"
end


it "should support the iOS 8 category key" do
n = APNS::Notification.new('device_token', {:alert => 'Hello iPhone', :badge => 3, :category => 'CATEGORY_IDENTIFIER'})
n.packaged_message.should == "{\"aps\":{\"alert\":\"Hello iPhone\",\"badge\":3,\"category\":\"CATEGORY_IDENTIFIER\"}}"
end

it "should not include keys that are empty in the JSON" do
n = APNS::Notification.new('device_token', {:badge => 3})
n.packaged_message.should == "{\"aps\":{\"badge\":3}}"
Expand All @@ -35,9 +40,9 @@
n = APNS::Notification.new('device_token', {:content_available => true})
n.packaged_message.should == "{\"aps\":{\"content-available\":1}}"
end

end

describe '#package_token' do
it "should package the token" do
n = APNS::Notification.new('<5b51030d d5bad758 fbad5004 bad35c31 e4e0f550 f77f20d4 f737bf8d 3d5524c6>', 'a')
Expand All @@ -52,5 +57,5 @@
Base64.encode64(n.packaged_notification).should == "AQAG3vLO/YTnAgBAeyJhcHMiOnsiYWxlcnQiOiJIZWxsbyBpUGhvbmUiLCJi\nYWRnZSI6Mywic291bmQiOiJhd2Vzb21lLmNhZiJ9fQMABGFhYWEEAAQAAAAA\nBQABCg==\n"
end
end

end