In order to enhance my Earthquake Alert! Android app, I wanted to be able to alert any user’s phone when an earthquake occurs anywhere in the world that matches some pre-defined filters. The end result was the Earthquake Alerter add-on app and it uses Google’s C2DM and Google App Engine to accomplish. This post describes how I accomplished this.
At a high level, to send a message to a user’s phone, I use Google’s C2DM (Cloud to device messaging) system which allows a direct connection to each user’s phone. Because these messages are pushed to the phone, minimal battery life is used. This also re-uses the same connection channel that other Google apps use (like Gmail, Talk, etc).
The basic overview of Earthquake Alerter and C2DM:
- User installs Earthquake Alerter add-on app
- User registers phone with my Google App Engine Server
- Cron job checks for earthquakes
- When a earthquake is new, my server sends a message to Google’s C2DM server containing the device ID and message to send the device
- User’s phone receives a message from C2DM
- The Alerter app receives this message and adds a status bar notification.
I started with the Chrome-to-phone open source project. This project provides a way to push interesting websites directly to your phone from the Chrome browser. It provided me with a base Android app and Google App Engine server code.
In particular, I was able to reuse the registration flow on both the app and server code. I make use of this to save a record of each registered device. I augmented it further to save some basic attributes about the user’s alert filters like minimum magnitude. This extra info allows me to perform some server side filtering of each quake without having to send it to the phone unnecessarily.
Checking for Earthquakes
On the server, I created a cron job that checks the USGS every couple of minutes. I wrote some basic logic to determine if any earthquake I receive is new and if so, I begin to alert each registered device. Checking for duplicates is actually important here because earthquakes can be reclassified a number of times after the event. If it were to be updated and I didn’t check for duplicates, then there’s a chance I could be sending multiple alerts of the same quake.
Sending the Alerts
To facilitate the actual earthquake alerts, I query for all the registered devices. I then add each device to a Task Queue (separate thread of execution). This Task Queue checks the device’s filters on the quake’s attributes, and if it passes, sends a message to Google’s C2DM server. I use a Task Queue for each device because you can execute these in parallel, significantly speeding up the total processing time. This time can be significant if the number of devices is high.
Adding the alert to the Status Bar
The Android app is registered to receive the actual earthquake message on the user’s phone. When it receives a message, it first needs to check any filters the server couldn’t check - namely “current location” type filters. Since a phone’s location is always changing, I delegate this filter to the client side. I may one day convert this check to be server-side, but it’s not a trivial task and I could see user’s not liking their location saved externally.
Earthquake Alerter Metrics
This add-on app and the accompanying App Engine server have been running for over 9 months will minimal interruption. Since I provide this app for free and don’t make anymoney off it, I appreciate how Google App Engine provides a decent quota for free. Occasionally I would hit these quotas (especially the number of Task Queues I start), but I’ve been able to optimize the code over the past 9 months to keep within the quotas.
This app currently has over 30,000 registered devices which is awesome! Since this number is pretty large, it can take up to 5-10 minutes to process sending alerts to each one. This duration would be significantly higher without using the parallel Task Queues.
Google App Engine is a very nice platform. This is my first real app for it and as such, there is a learning curve. I hope to continue learning their various tools to further optimize my app to use less quota, process devices more rapidly, and use less memory.