2016.9.4
2017.4.17

GCMでプッシュ通知を行う方法

今回はAndroidやiOSを搭載したモバイル端末に対してプッシュ通知を行う方法についてですが、結論から言うと、非常に面倒でした。

とくにGCM(Google Cloud Messaging)を利用してiOS端末に通知を送る場合、APNS(Apple Push Notification Service)というアップルが提供している通知サービスを利用しなくてはならず、通知に必要な手順は分かりずらいもので、気軽に導入できるとは言えない感じです。

動作確認にしてもAndroidは簡単にできますが、iOSの場合は、お金(税抜 11,800円)を払ってデベロッパーの登録を済ませないとできませんでした。アプリを公開するならまだしも、その前段階でお金を徴収するのはちょっとやめてほしいですね。

今回、GCMというGoogleのAPIを利用してプッシュ通知を行いますが、最新版(2016年9月現在)はFCM(Firebase Cloud Messaging)と呼ばれるものになります。Google API Consoleの「Google Cloud Messaging」でもリンク先はFCMとなっています。

ではなぜ、今回はGCMなのかというと「cordova-plugin-googlemaps」を利用している場合に「cordova-plugin-fcm」を導入して使おうとすると、そのままではビルドに失敗して動作しなかったからです。正常にビルドさせるために「build.gradle」をどーにかこーにかしないといけないっぽいのですが、そのどーにかこーにかの部分を色々試しましたが、どうにもなりませんでした。

残念ですが、FCMを利用したプッシュ通知は、また別の機会にやろうと思います。

目次

  • 開発環境
  • プラグインのインストール
  • Android端末に通知を行うための設定
  • iOS端末に通知を行うための設定
  • サンプルコード
  • 動作確認
  • iOS起動時のエラーについて
  • 通知データ送信時のエラーについて
  • FCMを導入しようとした際のビルドエラーについて
  • サーバ側の設定(Rubyの場合)

開発環境

  • [Windows] Visual Studio 2015
  • [Windows] Visual Studio Tools for Apache Cordova
  • [Mac] Xcode 7.3.1

プラグインのインストール

phonegap-plugin-push

プッシュ通知のプラグインはいくつかあるようですが、これが一番使いやすそうです。インストール方法はリンク先を参照してください。(Visual Studioを使用しているならconfig.xmlからインストールできます)

Android端末に通知を行うための設定

やるべきことは以下の通りです。

手順は調べれば出てくるの思うのでここでは割愛します。

  • Google API ConsoleのAPI「Google Cloud Messager」を有効に設定する。
  • Google API Consoleでプロジェクト、APIキーを作成し、プロジェクト番号とAPIキーを取得する。

iOS端末に通知を行うための設定

ビルドができる状態になっていることが前提。できない場合で、Visual Studioを利用している場合は以下のサイトを参考に、ビルド可能な状態にしてください。

iOS での Apache Cordova アプリの実行

iOS端末でも最終的に必要なのはプロジェクト番号とAPIキーの2つ。プロジェクト番号はAndroidと共通ですが、もう一つのAPIキーを入手するまでが大変です。

手順については以下の記事が分かりやすいと思います。

iOS で GCM(Google Cloud Messaging)のプッシュ通知を試す(前編) - Intelligent Technology's Technical Blog

iOS で GCM(Google Cloud Messaging)のプッシュ通知を試す(後編) - Intelligent Technology's Technical Blog

キーチェーンアクセスでp12形式のファイルが書き出しできない場合は、分類で「自分の証明書」を選択してから行ってください。私の場合、なぜか「すべての項目」からではできませんでした。(こちらを参考)

サンプルコード

下記はサンプルコード。

「senderID」にはプロジェクト番号をセットします。


var push = PushNotification.init({
    android: {
        senderID: "12xxxxxxxxxx"
    },
    ios: {
        senderID: "12xxxxxxxxxx",
        alert: true,
        badge: true,
        sound: true
    }
});

push.on('registration', function (data) {
    //alert("registrationId:" + data.registrationId);
    console.log(data);
    // 登録ID(data.registrationId)をサーバに送るなどして保存しておき、通知する際に利用する
});

push.on('notification', function (data) {
    //alert("notification:" + JSON.stringify(data));
    console.log(data);
});

push.on('error', function (e) {
    console.log(e);
});

Ionicフレームワークを利用している場合、上記のコードを「$ionicPlatform.ready()」内に配置すれば問題ないと思います。

設定可能な条件はこちらを参照。

動作確認

DHCというChrome拡張アプリを利用して動作確認を行います。(恥ずかしながら今回初めてこのアプリの存在を知りました。とても便利です。)

[Android] GCMのプッシュ通知を簡単にテストする方法 | Developers.IO

ChromeでREST APIをテストするならコレ!「DHC」 | mah365


設定内容は以下の通りです。

  • リクエストURL:https://gcm-http.googleapis.com/gcm/send
  • [HEADERS] Authorization:key=(APIキーを設定)
  • [HEADERS] Content-Type:application/json

下記はAndroid、iOSのテスト用通知データ。

「to」にはアプリ起動時に取得した登録ID(デバイストークン)をセットします。

【Androidの通知テスト用データ】


{
    "to":"xxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "data":{
        "title":"タイトル",
        "message":"メッセージ1
メッセージ2
メッセージ3", "soundname": "default" } }

【iOSの通知テスト用データ】


{
    "to":"xxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "notification" :{
        "title":"タイトル",
        "body":"メッセージ1\nメッセージ2\nメッセージ3",
      	"sound": "default"
    },
    "data":{
    }
}

Android、iOSともに他にも設定可能な条件があります。時間差で届いた複数のプッシュ通知をまとめて表示したり、逆に1行づつ表示したり、通知音を変更したり、通知時のバイブレーションの間隔を変更したりと他にも色々ありますが、それがAndroidとiOSでできたりできなかったりで、ちゃんとやるなら両方のOSのプッシュ通知の仕様を理解していないといけない感じです。

プラグインの設定やプッシュ通知のデータによってどのような通知が表示されるかは、下記のサイトを見るとイメージがつかみやすいと思います。

phonegap-plugin-push/PAYLOAD.md at master · phonegap/phonegap-plugin-push · GitHub

iOS起動時のエラーについて

プラグイン「phonegap-plugin-push」を利用している場合、iOSでのアプリ起動時に「PushNotification」が定義されておらず、エラー(ReferenceError: Can't find variable: PushNotification)が出る可能性があります。

プラグインのバグなのかなんなのか分かりませんが、その場合、config.xmlに以下の設定を追加して、iOSエンジンのバージョンを指定するとうまくいくようです。

<engine name="ios" spec="~4.1.1"/>


iOS 9.2: Reference Error: Can't find variable: PushNotification. · Issue #779 · phonegap/phonegap-plugin-push · GitHub

通知データ送信時のエラーについて

プッシュ通知の動作確認をしていると、たまに届くのかが遅かったり、以前はできていたのに今回はできなかったり、そもそも設定が悪くて表示できていなかったりと、なかなかうまくいかないことが多いです。(私は途中で投げ出しそうになりました。)

どうすればそういったことがなくなるのか...まあ、問題が出るたびに確認するしかないですよね。

以下、気を付けないといけないことが書いている記事のリンクになります。

APNSで通知が飛ばない場合に考えられる問題 - Qiita

iOS 9からAPNSデバイストークンがアプリインストールの度に変わるようになったようです - Qiita

APNs証明書更新手順 - Qiita

GCM自体が元々はAndroid用だったと思うので仕方ないですけど、主に自分に向けて記事をピックアップしていったら大体がiOSでの注意点でした。

FCMを導入しようとした際のビルドエラーについて

最初に書いたとおり、本当はFCMで通知処理を実装したかったのですが、プラグイン「cordova-plugin-fcm」と「cordova-plugin-googlemaps」を併用すると、ビルド時に以下のようなエラーが発生します。

「Please fix the version conflict either by updating the version of the google-services plugin (information about the latest version is available at https://bintray.com/android/android-tools/com.google.gms.google-services/) or updating the version of com.google.android.gms to 9.2.0.」

FCMを利用する場合の作法はこちらに載っていて、その通りにやってもやはり「cordova-plugin-googlemaps」を利用しようとするとダメでした。

...なぜ、なんでしょうね。

サーバ側の設定(Rubyの場合)

使用するプラグイン:gcm

インストール

gem install gcm

利用例(必要な箇所を抜き出して見繕っただけなので、動かないかも...)


require 'gcm'

begin
    # Android用
    gcm = GCM.new("Android用のAPIキー")
    response = gcm.send(
        ["xxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"], {
            data: {
                "title":"タイトル",
                "message":"メッセージ1<br/>メッセージ2<br/>メッセージ3",
                "soundname": "default"
            }
        })
    puts response.to_s

    # iOS用
    gcm = GCM.new("iOS用のAPIキー")
    response = gcm.send(
        ["xxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"], {
            notification: {
                "title":"タイトル",
                "body":"メッセージ1\nメッセージ2\nメッセージ3",
                "sound": "default"
            }
        })
    puts response.to_s
rescue => ex
    puts ex.message
end	

Windows環境でHTTPSを利用しようとすると、証明書エラー「SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed」が発生するので、プラグイン「certified」をインストールします。詳しくは以下の記事を確認してください。

ruby-2.0.0-rc2を入れた(サクッと) - There's an echo in my head

homebrew で入れた openssl を使って Ruby をコンパイルすると SSL 利用時に証明書エラーが発生する場合の対応 - Qiita

Cordova】関連記事