When I was developing our mobile multiplayer game ‘Drop It!’ I wanted to send notifications to the devices (Both Android and iOS) whenever a new move was made, or a random opponent was found. There are services online that offer you this kind of functionality (Like Urban Airship), but most of these services charge a monthly fee. Being Dutch I was looking for a way to implement this for free 😉 I found it, wrote a ColdFusion component called pusher.cfc and decided to share it with the community.
You can download the latest version of pusher by forking it from Github:
- Device registration (Both iOS and Android).
- Multiple devices per user (Also cross-platform).
- Connect a device to a specific user ID in your database (optional).
- Broadcast notifications to all your users
- Send push notifications to a specific user.
- Handle the removal of inactive devices.
- iOS: Supports both sandbox and production mode.
- Android: New canonical registration ID support.
- Both MS SQL and MySQL supported
- ColdFusion 8 or higher or Railo 3.x or higher
- A MySQL or MS SQL database
- Download pusher.zip
- An Apple SSL Push certificate (See this excellent blog by Raymond Camden on how to generate it). This should be a file with a .p12 file extention.
- Your Google GCM API key (See this post)
- Install all the jars from the /jar path into your ColdFusion class path
- Don’t forget to restart ColdFusion
Installation / configuration
- Download and extract pusher.cfc into your webroot.
- Edit pusher.cfc line 3 to reflect your DBMS (‘mssql’ or ‘mysql’).
- Edit pusher.cfc line 4 to set your datasource.
- Create a .cfm file and call the init() function pusher.cfc to create the neccesary database table:
<cfset pusher = createObject("component","pusher").init( mode = "development", appleCertificatePath = "C:\certificates\my.p12", appleCertificatePassword = "myPassword", googleAPIKey = "xxxxxxxxxxxxxxxxxxxxxxxx" )/>
Now your mobile app needs to start registering devices! Modify your iOS and/or Android app so that they call the following URL and make them pass the devices token:
<!-- Example 1: Register an anonymous Apple Device ---> http://localhost/pusher.cfc?method=registerDevice&deviceType=apple&token=xxxxx <!-- Example 2: Register an anonymous Android Device ---> http://localhost/pusher.cfc?method=registerDevice&deviceType=android&token=xxxxx <!-- Example 3: Register an userID with an Apple Device (Same goes for Android) ---> http://localhost/pusher.cfc?method=registerDevice&deviceType=apple&token=xxxxx&userID=123
These URL’s will pass back a simple JSON boolean to indicate if the call succeeded.
So we’ve registered a few devices, now what? It’s time to start sending messages! The following lines of code illustratie how you can broadcast messages or send messages to specific users.
<!--- Example 1: Broadcast a message to all your users ---> <cfset pusher.broadcastMessage(message = "Hello to all my users!")/> <!--- Example 2: Broadcast a message to a specific user ---> <cfset pusher.sendMessage(userID = 123, message = "Hello there!")/> <!--- Example 3: Broadcast a message to a specific user with a badge counter update ---> <cfset pusher.sendMessage(userID = 123, message = "Hello there!", badgeTotal = 3)/>
Cleaning inactive devices
Believe it or not, but sometimes users actually want to remove your app from their phone. We need to know about this so that we do not send notifications to these so-called ‘Inactive devices’. Pusher.cfc automatically handles inactive Android devices because we get immediate feedback after attempting to send a notification to an inactive device.
Apple however does not. We need to retrieve a list of inactive devices every now and then from Apple and then remove them from our database. This can be done by calling the ‘handleInactiveAppleDevices()’ function:
<!--- Example: Clean inactive apple devices ---> <cfset pusher.handleInactiveAppleDevices()/>
Good practice would be to implement the code above in a scheduled task and make it run once a day.
That’s it! I hope this help you out and saves you the countless hours I spent on trying to get this to work! 😉