こんにちは。
田中(邦)です。
今回はAmazon Simple Queue Service(Amazon SQS)とAmazon Simple Notification Service(SNS)を使ってAndroid端末にプッシュ通知を送信する仕組みを実装していきます。
イメージとしては
- プッシュ通知用のデータがアプリ側でMongoDBにどんどん登録されていく
- 貯まったデータをSQSに登録するrakeタスクを一定間隔で実行
- SQSに登録されたキューを取り出し、SNSを利用しAndroid端末にプッシュ通知を配信する
という感じです。
準備するもの
- Android端末 or GenymotionなどのGCMを利用したプッシュ通知が受信できるもの
- Genymotionで開発作業効率化d(๑╹ω╹๑ )
- クライアント側の実装はこちらを参考に
- Google Play Developer Consoleにアクセスできるアカウント
- AWSを利用できるアカウント
アプリの設定(Google Play)
- Google Developer Consoleにログインし、アプリを登録します
- Google Cloud Consoleにログインします
- Create Projectを選択し、新しいプロジェクトを作成します
- 一覧から先ほど作成したプロジェクトを選択します
- 画面左側のサイドバーからAPIsを選択し、”Google Cloud Messaging for Android”をONにします
- 次にサイドバーから今度はRegistered appsを選択し、画面上部の”REGISTER APP”を選択します
- PlatformにAndroidを選択し、”Accessing APIs directly from Android”と”Accessing APIs via a web server”を選択したものでそれぞれアプリケーションを登録します。NameはGoogle Developer Consoleで登録したものと同じで良いと思います
- 7で登録した”Accessing APIs via a web server”の方を一覧から選択し、Server Keyを開くと表示されるAPI KEYをコピーしておきます
- Google Developer Consoleを開き、1で登録したアプリを選択します
- 画面左側に表示されているサイドバーの”サービスとAPI”を選択し”別の送信者IDをリンク”をクリックします
- 8でコピーしておいたAPI KEYをここで入力すると、1で登録したものと7で登録したものがリンクされます
- サンプルを参考にしてアプリを作成し、Registration IDをサーバに登録できる仕組みを実装する。説明は割愛します
SQS,SNSの設定
次にSNSとSQSを設定します。
- まずSQSです。”Create New Queue”ボタンを選択肢、新しいキューを登録します。ここではSampleQueueとQueue Nameを設定しました
- 次にSNSです。SNSを開くとDashboardに”Add a New App”というボタンがあるので、そちらを選択します
- Push PlatformにGoogle Cloud Messaging(GCM)を選択し、API Keyに”アプリの設定(Google Play)” 8でコピーしたAPI KEYを入力してください。正しく設定できていれば画面左のAppsに(1)と表示されているはずです
- ついでにIAMでプッシュ通知専用のユーザを作っておくと良いかもしれません
rakeタスクの実装
前回開発したアプリにモデルやタスクを追加していきます。
- まずプッシュ通知用のモデルを作成します
padrino g model push_notification
を実行してください - モデルにフィールドを追加します
class PushNotification include Mongoid::Document include Mongoid::Timestamps # adds created_at and updated_at fields WAITING = 0 REGISTERED = 1 DELIVERED = 2 field :message, :type => String field :status, :type => Integer #0 => 未配信,1 => SQS登録済み 2 => 配信済み field :token, :type => String scope :waiting, where(:status => WAITING) scope :registered, where(:status => REGISTERED) scope :delivered, where(:status => DELIVERED) end
- タスクを作成します。 lib/tasksというディレクトリを作成し、その中にpush_notification.rakeというファイルを作成します。
# -*- encoding: utf-8 -*- ACCESS_KEY = 'your-aws-access-key' SECRET_KEY = 'your-aws-secret-key' SQS_ENDPOINT = 'sqs.ap-southeast-1.amazonaws.com' #使用しているリージョンにあわせて変更 SNS_REGION = 'ap-southeast-1' #使用しているリージョンにあわせて変更 QUEUE_NAME = 'SampleQueue' #SQSで設定したキューの名前 SNS_APPLICATION_ARN = "arn:aws:sns:ap-southeast-1:xxxxxxxxx:app/GCM/Sample" #snsに登録したアプリケーションのarn namespace :batch do desc 'SQSにキューを登録する' task :register_queue => :environment do sqs = AWS::SQS.new( :access_key_id => ACCESS_KEY, :secret_access_key => SECRET_KEY, :sqs_endpoint => SQS_ENDPOINT ).client queue_url = sqs.get_queue_url(:queue_name => QUEUE_NAME)[:queue_url] PushNotification.waiting.each do | notification| message = {:id => notification.id, :token => notification.token, :message => notification.message}.to_json sqs.send_message(:queue_url => queue_url, :message_body => message) notification.status = PushNotification::REGISTERED notification.save end end desc 'SQSからキューを取り出し、SNSでプッシュ通知を配信する' task :broadcast => :environment do sqs = AWS::SQS.new( :access_key_id => ACCESS_KEY, :secret_access_key => SECRET_KEY, :sqs_endpoint => SQS_ENDPOINT ).client queue_url = sqs.get_queue_url(:queue_name => QUEUE_NAME)[:queue_url] messages = sqs.receive_message(:queue_url => queue_url)[:messages] messages.each do |message| json = JSON.parse(message[:body]) broadcast_via_sns json end end end def broadcast_via_sns json sns = AWS::SNS.new( :access_key_id => ACCESS_KEY, :secret_access_key => SECRET_KEY, :region => SNS_REGION ) client = sns.client response = client.create_platform_endpoint( :platform_application_arn => SNS_APPLICATION_ARN, :token => json["token"] ) endpoint_arn = response[:endpoint_arn] client.publish(:target_arn => endpoint_arn, :message => json["message"]) notification = PushNotification.find_by_id json["id"] notification.status = PushNotification::DELIVERED notification.save end
- aws-sdkを利用するのでGemfileに下記を追記し、bundle installを実行します
gem 'aws-sdk'
- rake -T でタスク一覧を確認する。下記2行が表示されていればOK
rake batch:broadcast # SQSからキューを取り出し、SNSでプッシュ通知を配信する
rake batch:register_queue # SQSにキューを登録する - テスト用にデータを登録する。(実際にクライアントからRegistration IDを送信してサーバで登録しても良いし、めんどくさければpadrino consoleから登録しても良いです)
- rake batch:register_queue と rake batch:broadcast を順番に実行する
- プッシュ通知の受信を確認する
今回はコードをシンプルにするためにエラーのハンドリングやSQSやSNSの不要なレコードの削除などを行っていません。
モデルやタスクを修正すればiOSのプッシュ通知やE-mailでの通知などにも柔軟に対応できるんじゃないかと思います。
ソースはこちらに置いておきます。