push-notify-general- A general library for sending/receiving push notif. through dif. services.

Safe HaskellNone




The purpose of this library

This library defines a general API for communicating with iOS, Android and WPhone powered devices, sending/receiving Push Notifications.

The main idea is to hide as much as possible the differences between the different services.

Push Notification services in general, are very similar. They all are asynchronous, best-effort services that offer third-party developers a channel to send data to apps from a cloud service in a power-efficient manner. The main differences between them, refer to details as: the maxim payload length, the quality of service, queueing the messages or not, and the time limit for this, the way the messages are handled on devices, etc.

The registration of devices is very similar too. The device/app gets a unique ID provided by the different services, and sends this identifier to your 3rd party server. So then, when you want to send messages to these devices, you have to send them to the Push Servers, and they will deliver the messages to the proper devices.

So, Device will be our general identifier.

How to use this library

All the communication with devices will be abstracted behind the PushManager data type.

You will reference to it when intending to send notifications. Also, if you properly set the callback functions, you will be able to receive messages from devices.

So, the mains steps:

  • First you establish the main configuration for the push service: PushServiceConfig . This means, set the configurations for the different Push services you want to use, and also set the callbacks functions. These functions could be used to actualize a DB, do some processing in background, etc.
  • Then you start the service with the startPushService function and you get the PushManager. So, you can add this subsite to your Yesod app or just ignore it if you don't want to receive messages from devices.
  • When you want to send notifications:
  1. You have to specify the PushNotification , setting the parameters. Here you have to do it for each kind of notification, because they contain different structures.
  2. Then, you can send these with the sendPush function, passing the PushManager as an argument. Also, you can get useful information from the PushResult value after communicating with servers.

When your Apps on devices need to send an upstream message they have 2 options:

  1. Messages through CCS (only Android devices). For this you have to set the proper CCS settings when starting the Push Service.
  2. Messages as HTTP requests to PushManager Yesod subsite (all devices). (using the route of the Yesod subsite: something like ".../messages" )

You can see many test examples on the GitHub repository: https://github.com/MarcosPividori/GSoC-Communicating-with-mobile-devices

PushManager Subsite

Everytime a device sends a message to our system as HTTP POST request it should provide the pair {"regId" : identifier , "system" : system } specifing the ID and the system running on the device, so we can build the Device identifier.

Now we support APNS, MPNS and GCM. So the possible combinations are:

{ "regId" : RegId , "system" : "ANDROID" }

{ "regId" : DeviceURI , "system" : "WPHONE" }

{ "regId" : DeviceToken , "system" : "IOS" } (token stored in hexadecimal representation)

This PushManager Yesod subsite consists of 2 routes for receiving JSON data:

  • /register -> this route will receive the registration from devices. So devices have to send the pairs {"regId" : identifier , "system" : system } and any extra information. When a new intent for a registration arrives, the newDeviceCallback function will be called with the identifier and JSON data as arguments so you can ask for more information as username and password, etc. Depending on the callback function result, the response to the POST request will be set, so device can know if it has successfully registered on the server.
  • /messages -> this route will receive POST messages from devices. Again, devices have to send the pairs {"regId" : identifier , "system" : system } and any other extra information. Everytime a new messages arrives to the Yesod subsite, the newMessageCallback function will be called with the identifier and JSON data as arguments. This abstraction lets us use the same callback function to handle the messages that arrive from CCS too (XMPP connection for GCM).

Push Service

startPushService :: PushServiceConfig -> IO PushManagerSource

startPushService starts the PushService creating a PushManager.

closePushService :: PushManager -> IO ()Source

closePushService stops the Push service.

sendPush :: PushManager -> PushNotification -> HashSet Device -> IO PushResultSource

sendPush sends messages to the appropiate Push Servers.

withPushManager :: PushServiceConfig -> (PushManager -> IO a) -> IO aSource

withPushManager creates a new manager, uses it in the provided function, and then releases it.

Push Manager

data PushManager Source

Main manager for the Push Service.

This PushManager will be used to send notifications and also can be added as a subsite to a Yesod app in order to receive registrations and messages from devices as HTTP POST requests.

Push Settings

data Device Source

Unique identifier of an app/device.



An Android app.

APNS DeviceToken

An iOS app.


A WPhone app.

data PushServiceConfig Source

Main settings for the Push Service.




pushConfig :: PushConfig

Main configuration.

newMessageCallback :: Device -> Value -> IO ()

The callback function to be called when receiving messages from devices (This means through the CCS connection or as POST requests to the Yesod subsite).

newDeviceCallback :: Device -> Value -> IO RegisterResult

The callback function to be called when a new device try to register on server.

unRegisteredCallback :: Device -> IO ()

The callback function to be called when a device unregisters.

newIdCallback :: (Device, Device) -> IO ()

The callback function to be called when a device's identifier changes.

data RegisterResult Source

RegisterResult represents the result of a device attempting to register


ErrorReg Text 

data PushConfig Source

Main settings for the different Push Services. Nothing means the service won't be used.


data GCMConfig Source

Settings for GCM service.

Push Message

generalNotif :: Object -> IO PushNotificationSource

generalNotif builds a general notification from JSON data.

If data length exceeds 256 bytes (max payload limit for APNS) it will fails.

For MPNS, data will be XML-labeled as "jsonData".

Push Result

data PushResult Source

PushResult represents a general result after communicating with a Push Server.




successful :: HashSet Device

Notifications that were successfully sent.

failed :: HashMap Device (Either Text SomeException)

Notifications that were not successfully sent.

toResend :: HashSet Device

Failed notifications that you need to resend, because servers were not available or there was a problem with the connection.

unRegistered :: HashSet Device

Set of unregistered devices.

newIds :: HashMap Device Device

Map of devices which have changed their identifiers. (old -> new)