Sinatra + HoustonでPush通知
Sinatra + houstonでPush通知
再びSinatraに戻って、今度はiPhoneへのPush通知送信に挑戦してみました。
はじめに
Rubyを使って通知を送信できるライブラリはいくつかあるようですが、比較的易しそうな感じがしたのでHoustonを試してみることに。
Pushの送信側は以前作成したものに追加する形としました。
pemファイルの作成
まずは証明書や送信側で必要となるpemファイルの作成から(実はここを曖昧なまま進めたせいでどハマりしました)。
以下のようなサイトを参考に、Push Notificationを有効にした証明書を作成します。
「2. サーバ用PEMファイルの作成」に従ってpemファイルを作成しても問題ありませんが、HoustonのREADME > Converting Your Certificateの通り、Keychainで[Apple Development IOS Push Services:自分のアプリのID]の証明書、秘密鍵をShiftキーで両方選択 > 2個を書き出す... でp12ファイルを作成し、以下のコマンドを実行すると一発で目的のpemファイルを作成できます。
openssl pkcs12 -in 書き出したp12ファイル名.p12 -out 出力するpemファイル名.pem -nodes -clcerts
作成したpemファイルをSinatraのプロジェクトフォルダ以下に置きます。
なお、どハマりしていた時の症状は、Push通知を送信すると成功した旨のメッセージが返るのに、デバイスに通知は来ない、というもの。
同じような症状に見舞われた場合は証明書やpemファイルの作成を疑ってみると良いかもしれません。
iOSアプリの作成とトークンの取得
pemファイルの作成時に指定したアプリのIDで、iOSアプリ(プロジェクト)を作成します。
今回も[Single View Application]でプロジェクトを作成してみました。
プロジェクトのAppDelegate.mを以下のように変更します。
iOS8ではHoustonのREADMEで紹介されているコードは一部Deprecatedになったようで、丸写しすると警告が表示されました。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Push Notificationの準備 UIUserNotificationType types = UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert; UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil]; [application registerUserNotificationSettings:mySettings]; return YES; } - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { // Push通知がユーザーに許可されたらメソッドを呼び出してトークンを取得する. [application registerForRemoteNotifications]; } - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // Push通知送信側で使用するトークンが取得できる. NSLog(@"Token: %@", deviceToken); } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { // エラー. NSLog(@"Error: %@", error); } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // Push通知を受け取ったら実行.notification.custom_dataの内容がuserInfoに含まれる. NSLog(@"UserInfo: %@",userInfo); }
これを実機(今回はiPhoen)で実行すると、Push通知の許可を求めるアラートが表示され、OKならNSLogでトークンが出力されます。
このトークンと、pemファイルの作成で作成したpemファイルを使って以下のコマンドをTerminalで実行するとPush通知がiPhoneに届きます。
apn push "" -c /pemファイルのパス/pemファイル名.pem -m "世界さんチーっす"
ちなみに"-m"以降を削除した場合、VimでPush通知本文の入力が求められますが、deleteキーを使うと前の文字が大文字になったりして通常のものとは若干操作が違っていてちょっと苦労しました
(Vimの操作に慣れていないだけかもしれませんが)。
あと、トークンは最初に実行した時はエラーは出ないもののうまく取得できず、半日ほど放置したら取れるようになった、ということがありました。
証明書などの登録に時間がかかるなどあるのかもしれません。
SinatraへのPush通知送信機能の追加
Houstonのサイト > Usageのコードを、[localhost:XXXX/push]にアクセスした場合に実行されるようにしてみました。
app.rb
require 'coffee-script' require 'sass' require 'sinatra' require 'sinatra/base' # サーバーを再起動しなくてもリロードする require 'sinatra/reloader' require 'slim' require 'houston' class MainApp < Sinatra::Base isUninitialized = true # localhost:XXXXにアクセスしたらTopページを表示する get '/' do slim :top end get '/about' do slim :top end get '/css/stylesheet.css' do sass :'css/style' end get '/js/javascript.js' do coffee :'js/script' end get '/push' do # 初期化済みならスルー. if isUninitialized # 開発用のURLを指定. APN = Houston::Client.development APN.certificate = File.read("forPushTest.pem") # デバイスから取得したトークンをセット. # TODO: Appからトークンを送信するようにして、それを使用するよう変更. token = "" # 取得したトークンから通知を作成する. notification = Houston::Notification.new(device: token) notification.alert = "世界さんチーっす!" # 受信した時に付与されるバッジ数の設定. notification.badge = 1 notification.sound = "sosumi.aiff" notification.category = "INVITE_CATEGORY" notification.content_available = true # 独自のパラメータを付与. notification.custom_data = {pushtest: "送信しました"} isUninitialized = false end # Push通知を送る. APN.push(notification) end end
- 今回追加したところは緑にしています。
- Gemfileにも[gem 'houston', '2.2.1']を追加しています。
Xcodeで作成したiOSアプリを実行して、didReceiveRemoteNotificationで取得できるuserInfoを調べてやると、以下のように[notification.custom_data]でセットしたパラメータを受け取っていることが確認できます。
今回はほぼサンプルのままでしたが、何かのタイミングでiPhoneからURLにアクセス -> Push通知 としても面白そうですね。
参考
Houston
- nomad/houston - GitHub
- iPhoneアプリのPush通知をRubyで実装するならhoustonが良さげ - Qiita
- Ruby で APNS を行う(houston) - Programmer's Report
証明書、pemファイルの作成
- Apple Push Notification Serviceを使ってiOSにプッシュ通知をするために必要な証明書の準備方法 - ggった結果
iOSでのPush通知
- Local およびPush Notificationプログラミングガイド - Apple Developer
- APNS - iOS8からのプッシュ通知 - Qiita
- Xcode6でiOS8へPush通知が送れない場合の解決方法 - Qiita
- [iOS 8] UILocalNotification もユーザー認証が必要になりました - Developers.IO
- Heroku+RailsでiOSに簡単プッシュ #ハツカソン - Morizotter Blog