Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

banjo-apn_sender

Package Overview
Dependencies
Maintainers
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

banjo-apn_sender

  • 2.4.0
  • Rubygems
  • Socket score

Version published
Maintainers
2
Created
Source

== Synopsis

Based on Kali Donovan's APN sender 1.x.

In 2.0 we keep things lean - we removed the resque layer, and make APN connection pluggable to multithreaded background worker (like SideKiq) to send Apple Push Notifications over a persistent TCP socket.

== The Story

So you're building the server component of an iPhone application in Ruby. And you want to send background notifications through the Apple Push Notification servers, which doesn't seem too bad at first. But then you read in the {Apple Documentation}[https://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/WhatAreRemoteNotif/WhatAreRemoteNotif.html#//apple_ref/doc/uid/TP40008194-CH102-SW7] that Apple's servers may treat non-persistent connections as a Denial of Service attack, and you realize that Rails has no easy way to maintain a persistent connection internally, and things start looking more complicated.

The apn_sender 2.0 gem is pluggable to run on delayed job workers, and processes background messages from your application and sends them along to Apple over a single, persistent socket.

Same as 1.x, it also includes the ability to query the Feedback service, helper methods for enqueueing your jobs.

== Yet another ApplePushNotification interface?

Yup. There's some great code out there already, but we didn't like the idea of getting banned from the APN gateway for establishing a new connection each time we needed to send a batch of messages, and none of the libraries I found handled maintaining a persistent connection.

== Usage

=== 0. Setting up the pem certs

Put your apn_production.pem and apn_production_sandbox.pem certificates from Apple in your RAILS_ROOT/config/certs directory.

=== 1. Sending Messages From Your Application

To send a message through Apple's Push Notification service from your Rails application:

APN::Connection.send(token, options, sandbox)

where, +token+ is the unique identifier of the iPhone to receive the notification +sandbox+ is a boolean to indicate if you are using the APN sandbox push server +options+ can have any of the following keys:

:alert #=> The alert to send

:badge #=> The badge number to send

:sound #=> The sound file to play on receipt, or true to play the default sound installed with your app

:custom #=> Anything else that goes to the root of the message

If any other keys are present they'll be added to the root of the aps hash

=== 2. Sending as Queued Message using delayed processes, ie: SideKiq as the example here

class ApnSideKiqWorker sidekiq_options queue: :apn

def perform(token, options, sandbox = false)
  APN::Connection.send(token, options, sandbox)
end

end

options = { alert: 'Hello from APN', sound: 'default.wav', badge: 10, extra: { id: 1234 } } ApnSideKiqWorker.perform_async(device.token, options, device.build == 'development')

Once this is done, you can fire off the SideKiq background worker with

$ sidekiq -c 5 -q apn

=== 3. Checking Apple's Feedback Service

Since push notifications are a fire-and-forget sorta deal, where you get no indication if your message was received (or if the specified recipient even exists), Apple needed to come up with some other way to ensure their network isn't clogged with thousands of bogus messages (e.g. from developers sending messages to phones where their application used to be installed, but where the user has since removed it). Hence, the Feedback Service.

It's actually really simple - you connect to them periodically and they give you a big dump of tokens you shouldn't send to anymore. The gem wraps this up nicely -- just call:

APN::Feedback accepts the same optional :environment and :cert_path / :full_cert_path options as APN::Sender

feedback = APN::Feedback.new()

tokens = feedback.tokens # => Array of device tokens tokens.each do |token| # ... custom logic here to stop you app from # sending further notifications to this token end

If you're interested in knowing exactly when Apple determined each token was expired (which can be useful in determining if the application re-registered with your service since it first appeared in the expired queue):

items = feedback.data # => Array of APN::FeedbackItem elements items.each do |item| item.token item.timestamp # ... custom logic here end

The Feedback Service works as a big queue. When you connect it pops off all its data and sends it over the wire at once, which means connecting a second time will return an empty array, so for ease of use a call to either +tokens+ or +data+ will connect once and cache the data. If you call either one again it'll continue to use its cached version (rather than connecting to Apple a second time to retrieve an empty array, which is probably not what you want).

Forcing a reconnect is as easy as calling either method with the single parameter +true+, but be sure you've already used the existing data because you'll never get it back.

==== Warning: No really, check Apple's Feedback Service occasionally

If you're sending notifications, you should definitely call one of the receive methods periodically, as Apple's policies require it and they apparently monitor providers for compliance. I'd definitely recommend throwing together a quick rake task to take care of this for you (the {whenever library}[http://github.com/javan/whenever] provides a nice wrapper around scheduling tasks to run at certain times (for systems with cron enabled)).

Just for the record, this is essentially what you want to have whenever run periodically for you:

def self.clear_uninstalled_applications feedback_data = APN::Feedback.new(:environment => :production).data

feedback_data.each do |item|
  user = User.find_by_iphone_token( item.token )
  
  if user.iphone_token_updated_at && user.iphone_token_updated_at > item.timestamp
    return true # App has been reregistered since Apple determined it'd been uninstalled
  else
    user.update_attributes(:iphone_token => nil, :iphone_token_updated_at => Time.now) 
  end
end

end

== Installation

Add this to your Gemfile:

gem 'apn_sender', :require => 'apn'

Then bunndle,

$ bundle install

== Copyright

Copyright (c) 2010 Kali Donovan. See LICENSE for details.

FAQs

Package last updated on 03 Oct 2014

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc