Google App EngineからiOSアプリへPush通知が送れるようになりました

Google App Engine 1.7.7のアップデートでソケット接続がサポートされたことによってAppleのPush Notification Serviceが使えるようになりました。

Outbound sockets is now in preview in this release for Java and Python. With outbound sockets, billing-enabled App Engine applications can now make outbound connections with TCP or UDP sockets. This allows developers to build applications that weren’t previously possible on App Engine, such as IMAP or DNS clients.

In the Python runtime, we’ve added support for the Python SSL Library, so you can now open secure connections to remote services such as Apple’s Push Notification service.

アプリのバックエンドにApp Engineを使っているデベロッパーがリモートプッシュ通知機能を提供したい場合、これまで外部のUrban AirshipやParse等のサービスで補助、またはAWSなどで追加サーバーを用意する必要がありました。

やってみよう

2009年から要望されているのをウォッチしていたので喜びのあまりPython SDKで速攻試しました。*1

1. Push Notificationに対応したアプリの証明書などの準備
2. デバイストークンをサーバーへ送信する仕組み
3. サーバー上に保管してあるトークンから各ユーザーへPush通知を送信する仕組み

1. 2. は省略しています。以下公式ドキュメントなどを参考してください


今回はAPNsサーバーとの通信処理にPyAPNsというライブラリを使いました。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import webapp2

# https://raw.github.com/simonwhitaker/PyAPNs/master/apns.py
from apns import APNs, Payload

apns = APNs(use_sandbox=False, cert_file='cert.pem', key_file='key.pem')  # 本番
#apns = APNs(use_sandbox=True, cert_file='cert.pem', key_file='key.pem') # サンドボックス
token_hex = '41488ad67957e82b3005f88c3c95c9041b3bb91156e9b9165d8f108f2422d4e9' # ここは各ユーザーのデバイストークン(HEX)に変える

class APNsHandler(webapp2.RequestHandler):
    def post(self):
        alert = self.request.params.get('alert')
        sound = self.request.params.get('sound')
        badge = self.request.params.get('badge')
        payload = Payload(alert, sound, badge)

        apns.gateway_server.send_notification(token_hex, payload)
        self.response.write(u"Sent a notification message.")


app = webapp2.WSGIApplication([
    ('/notify', APNsHandler)
], debug=True)

いくつか注意点があります

app.yamlでライブラリにsslを追加する

libraries:
- name: ssl
  version: latest

以下に詳細があります

開発サーバー(devappserver2)では動かない

OS XUbuntuで試したんですが import _ssl が通らずに例外発生します(import socket自体は使える)。
原因不明だったのでローカルでの確認はパスして本番サーバーで確認しました。

本番環境で課金を有効にする必要がある

これはエラーメッセージでそう出るのでやればわかるはず。

あと今回のアップデートで課金の制限も廃止されたそうですよ。先のリリースに書いてある*2。僕は一旦支払いしてから$0にしてみました。どういう請求がくるのかは不明。

テスト

ターミナルなどから

curl -d"alert=テスト" "http://XXX.appspot.com/notify"

とする

*1:Java SDK版は Blog @vierjp : Google App Engine/Java 1.7.7でiPhoneにPush通知してみた をどうぞ

*2:しばらく使ってなかったのでどう変ったのかくわしくない