HTTP2-compliant wrapper for sending iOS and Android push notifications.
Add pigeon and kadabra as mix.exs dependencies:
defdepsdo[{:pigeon,"~> 1.5.1"},{:kadabra,"~> 0.4.4"}]endAdd a default worker config to your mix config. See the detailed docs for setting up your certificate and key.
config:pigeon,:apns,apns_default: %{cert: "cert.pem",key: "key_unencrypted.pem",mode: :dev}
This config sets up a default connection to APNS servers.
certandkeycan be any of the following:- Static file path
- Full-text string of the file contents
{:my_app, "certs/cert.pem"}(indicates path relative to theprivfolder of the given application)
Alternatively, you can use token based authentication:
config:pigeon,:apns,apns_default: %{key: "AuthKey.p8",key_identifier: "ABC1234567",team_id: "DEF8901234",mode: :dev}
:key- Created and downloaded via your developer account. Like:certthis can be a file path, file contents string or tuple:key_identifier- The 10-character key identifier associated with:key, obtained from your developer account:team_id- Your 10-character Team ID, obtained from your developer account
Create a notification packet. Note: Your push topic is generally the app's bundle identifier.
iex>n=Pigeon.APNS.Notification.new("your message","your device token","your push topic (optional)")
Send the packet. Pushes are synchronous and return the notification with an updated
:responsekey.iex>Pigeon.APNS.push(n)%Pigeon.APNS.Notification{device_token: "your device token",expiration: nil,id: "963B9FDA-EA60-E869-AAB5-9C88C8E7396B",payload: %{"aps"=>%{"alert"=>"your message"}},response: :success,topic: "your push topic"}# Add an `:on_response` callback for async pushes.iex>Pigeon.APNS.push(n,on_response: fn(x)->IO.inspect(x)end):ok
Additional documentation: APNS (Apple iOS)
Looking for GCM? Try v0.13 or earlier.
Add a default worker config to your mix config.
config:pigeon,:fcm,fcm_default: %{key: "your_fcm_key_here"}
Create a notification packet. FCM notifications support
iex>msg=%{"body"=>"your message"}iex>n=Pigeon.FCM.Notification.new("your device registration ID",msg)
Send the packet. Pushes are synchronous and return the notification with updated
:statusand:responsekeys. If:statusis success,:responsewill contain a keyword list of individual registration ID responses.iex>Pigeon.FCM.push(n)%Pigeon.FCM.Notification{message_id: "0:1512580747839227%8911a9178911a917",payload: %{"notification"=>%{"body"=>"your message"}},priority: :normal,registration_id: "your device registration ID",response: [success: "your device registration ID"],status: :success}# Add an `:on_response` callback for async pushes.iex>Pigeon.FCM.push(n,on_response: fn(x)->IO.inspect(x)end):ok
Additional documentation: FCM (Android)
Add a default worker config to your mix config.
config:pigeon,:adm,adm_default: %{client_id: "your_oauth2_client_id_here",client_secret: "your_oauth2_client_secret_here"}
Create a notification packet.
iex>msg=%{"body"=>"your message"}iex>n=Pigeon.ADM.Notification.new("your device registration ID",msg)
Send the packet.
iex>Pigeon.ADM.push(n)%Pigeon.ADM.Notification{consolidation_key: nil,expires_after: 604800,md5: "M13RuG4uDWqajseQcCiyiw==",payload: %{"data"=>%{"body"=>"your message"}},registration_id: "your device registration ID",response: :success,updated_registration_id: nil}# Add an `:on_response` callback for async pushes.iex>Pigeon.ADM.push(n,on_response: fn(x)->IO.inspect(x)end):ok
Additional documentation: ADM (Amazon Android)
Workers may be specified at application startup by creating a module containing functions that return zero or more configuration structures appropriate to the push service being enabled.
Specify these in your config.exs as:
config:pigeon,workers: [{YourApp.Pigeon,:apns_config},{YourApp.Pigeon,:fcm_config},{YourApp.Pigeon,:adm_config}]These should be implemented as:
defmoduleYourApp.Pigeondo@moduledocfalse@push_modeif(Mix.env()==:production,do: :prod,else: :dev)defapns_configdoPigeon.APNS.ConfigParser.parse(key: System.get_env("APNS_KEY"),key_identifier: System.get_env("APNS_KEY_ID"),team_id: System.get_env("APNS_TEAM_ID"),mode: @push_mode,name: :apns_default)enddeffcm_configdoPigeon.FCM.Config.new(name: :fcm_default,key: System.get_env("FCM_SERVER_KEY"))endendIf your startup configuration requires reading your configuration from a database or using another dependency that needs a database, startup is a little more complex.
Modify your
mix.exsto not startpigeonby default:defdepsdo[{:pigeon,"~> 1.3.1",runtime: false},{:kadabra,"~> 0.4.4"},{:ecto,"~> 2.0 or ~> 3.0"}]end
Modify
config.exsto specify a single worker function:config:pigeon,workers: [{YourApp.Pigeon,:config}]
Modify your main application to start
pigeonafter yourRepohas been started under your application’s supervision tree:defstart(_type,_args)dochildren=[YourApp.Repo,]opts=[strategy: :one_for_one,name: YourApp.Supervisor]with{:ok,sup}<-Supervisor.start_link(children,opts),{:ok,_}<-Application.ensure_all_started(:pigeon,:permanent)do{:ok,sup}endend
Implement your database query as part of your Pigeon module:
defmoduleYourApp.Pigeondo@moduledocfalsealiasYourApp.{PushApplication,Repo}defconfig_workersdoPushApplication|>Repo.all()|>Enum.map(&build_config/1)enddefpbuild_config(%{type: "apns"}=config)Pigeon.APNS.ConfigParser.parse(key: config.key,key_identifier: config.key_identifier,team_id: config.team_id,mode: config.mode,name: Atom.to_string(config.name)# This is bad, but keep it simple!)enddefpbuild_config(%{type: "fcm"}=config)doPigeon.FCM.Config.new(name: Atom.to_string(config.name),key: config.key)endend
