LoginSignup
26
28

More than 5 years have passed since last update.

AWSのSNSを利用してスマホにプッシュを送信する(初級編)

Last updated at Posted at 2015-06-19

概要

AWSにはSNSというサービスがあり、高速かつ確実かつ安価にスマホにプッシュが送れますよというものです。

本来、PHPでiOSへのプッシュとAndroidのプッシュに対応しようとすると、それぞれに合わせたプログラムを書く必要がありますが、SNSを使えばそんなに頑張らなくてもいろいろな端末に対して見境なくプッシュを発射できるようになります。

環境

  • EC2サーバー(APIサーバー)
  • nginx 1.6.2
  • php-fpm 5.5.25
  • CakePHP 2.5.3

環境が変わってもプログラムがちょっと変わるだけでやり方は一緒です。

仕組み

例えば、Aという端末からBという端末に対してプッシュでメッセージを送るアプリを考えてみます。LINEみたいなやつね。

これまでのやり方(SNSを使わない方法)

まず、プッシュトークンを下の図のように取得して、APIサーバーを介してユーザーIDとプッシュトークンが紐付いた状態でDBに保持しておきます。

スライド1.png

iOSの場合プッシュトークンはほとんど変わることはないようですが、念のため起動時毎回プッシュトークンの取得をするように書いたりします。お好みで。

Androidの場合はよくプッシュトークンが変わるので、こちらは起動時なり、前回取得から一定時間経過したら取得し直すなりするように実装しておきます。お好みで。

実際にプッシュを打つ際は、メッセージを送る相手のユーザーIDとメッセージなどをAPIサーバーへ送り、相手がAndroidならCGMサーバーを、iOSならAPNSサーバーを(以下面倒なのでプッシュサーバーと記載)叩きます。するとプッシュサーバーから対象の端末へプッシュが飛びます。

スライド2.png

SNSを使う方法

まず、プッシュトークンを下の図のように取得して、APIサーバーにユーザーIDとプッシュトークンを送ります。ここで、このままDBに保存せず、プッシュトークンをSNSに送ります。

するとEndpoint Arnが返ってきます。これとユーザーIDを紐付いた状態でDBに保存します。

スライド3.png

プッシュトークンはDBに保存しておいても、保存しておかなくてもOKです。プッシュトークンが変わった時だけSNSのAPIを叩きたいということならプッシュトークンも一緒にDBに保存しておきます。

そして、実際にプッシュを打つ時は、メッセージを送る相手のユーザーIDとメッセージをAPIサーバーに送るところまでは一緒ですが、APIサーバーは受け取った後にユーザーIDからEndpoint ArnをDBから取得してSNSにメッセージとEndpoint Arnを送ります。

するとどうでしょう。相手がAndroidだろうが、iOSだろうが、SNSがプッシュサーバーをうまいこと叩いてくれて、メッセージ届きます。すごい。

スライド4.png

準備

まずは、PHPから直接プッシュをアプリに送れる状態にまでしてください。
やり方はどっかを参照すべし。

プログラム

アプリ側は特にいじる必要はありません。

サーバー側は AWS SDK for PHP をまずダウンロードして下さい。このSDK使うと楽ちんです。
そして私はSNSというモデルを作ってみました。これをうまいこと使えばいけるはずです。
やり方は人それぞれだと思うので、一例だと思ってください。

<?php
require_once APP . 'Vendor/aws-sdk-php/vendor/autoload.php';
use Aws\Common\Aws;
use Aws\Common\Enum\Region;

class SNS extends AppModel
{
    private $obj = null;

    private function getInstance()
    {
        if (is_null($this->obj)) {
            $this->obj = Aws::factory([
                'key'    => AWS_IAM_KEY,    // AWSのIAMに登録したキー
                'secret' => AWS_IAM_SECRET, // AWSのIAMに登録したシークレット
                'region' => Region::TOKYO   // リージョンは自分の環境に合わせるべし
            ])->get('sns');
        }
        return $this->obj;
    }

    /**
     * SNSにプッシュトーンを登録してEndpointArnを取得
     */
    public function createPlatformEndpoint($token)
    {
        $options = [
            'Token'                  => $token,
            'PlatformApplicationArn' => (strlen($token) == 64 ? ARN_IOS: ARN_ANDROID), // トークンの文字数によってiOSかAndroidか指定してます。もっといい方法あったら教えて
        ];
        try {
            $res = $this->getInstance()->createPlatformEndpoint($options);
        } catch (Exception $e) {
            $this->log($e->getMessage(), 'error');
            return false;
        }
        return $res['EndpointArn']; // ←戻り値見るとEndpointArnがわかります
    }

    /**
     * プッシュ!
     */
    public function publish($message, $EndpointArn)
    {
        try {
            $res = $this->getInstance()->publish([
                'Message'   => $message,
                'TargetArn' => $EndpointArn
            ]);
        } catch (Exception $e) {
            $this->log($e->getMessage(), 'error');
            return false;
        }
        return $res;
    }
}

まとめ

面倒だったらSNS使わないでAPIサーバーから直接プッシュサーバーを叩いてもいいよ。けど、ユーザー数が増えてくるとすごく時間かかるし、その間、サーバーのCPU使用率はギュンギュンです。

だからSNS使ったほうがいいです。SNSしゅごい(^q^)

26
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
28