iOSとAndroidアプリにプッシュ通知をBluemixから送ってみる。

スマホを使っていると、ピコン！と届く、あのプッシュ通知は、ユーザーを、あなたの作ったアプリに振り向いてもらうワザのひとつです。いわゆるiOSでは、Apple Push Notification service (APNS)、AndroidではGoogle Cloud Messaging (GCM)というサービスが、その機能を提供してる。

## Bluemixでプッシュ通知する手段は、1つじゃない
さてBluemixでiOS、Androidのプッシュ通知を送信・管理する方法は、パッと思いつくだけで、3種類。

| <img width="121" alt="IMFPush.png" src="https://qiita-image-store.s3.amazonaws.com/0/75507/10d6fe9b-14fd-a229-fb54-82a130d9a7d3.png"> | <img width="133" alt="MFP.png" src="https://qiita-image-store.s3.amazonaws.com/0/75507/2abfe580-aae1-6e3f-69e6-79a690d8fdcc.png">  | <img width="150" alt="LB.png" src="https://qiita-image-store.s3.amazonaws.com/0/75507/5d543c31-4ad5-67e5-565d-c78c34c425b6.png"> |
|:-----------:|:------------:|:------------:|
| IMFPush    | MobileFirst Platform       |    Node.js <br /> LoopBack     |
|iOS, Android|iOS, Android<br />Windows 8/10| iOS, Android|
|単機能|多機能|？|
|[ガイド](https://www.ng.bluemix.net/docs/services/mobilepush/index.html "Qiita")|[ガイド](https://developer.ibm.com/mobilefirstplatform/documentation/getting-started-7-1/foundation/notifications/push-notifications-overview/)|[ガイド](https://docs.strongloop.com/display/public/LB/Push+notifications)|

さらにプッシュ通知つながりで見ると、PaaSであるBluemix以外に、この他にマーケティング機能と連携した[Silverpop](http://www.silverpop.com/Software/Mobile-Customer-Engagement)というSaaSサービスもあるので、Bluemixでのプッシュ通知では物足りないヒトは、こっちをチェックするのも良いかも知れない。まず、この記事では、シンプルなプッシュ通知である IBM Push Notificationsサービス(IMFPush)について書く。地味に、Cordovaプラグイン対応もしている。

## 2015年12月4日にガイド(英語版)が新しくなってた
じきに翻訳されると思うが、12月にガイドが新しくなってるので、がんばって英語の方を見るのが、オススメ。その中でも、ハマりそうなポイントやセットアップ方法を中心にメモメモ...。
[公式ガイド](https://www.ng.bluemix.net/docs/#services/mobilepush/index.html)

## 価格感
100万通まで無料。それを超えると100万通毎に2,100円/月。(2015年12月現在) よくある価格帯...

## ザックリこんなこと出来ました

1. Bluemixのダッシュボードからメッセージを入力して、アプリにプッシュ通知を送る
<img width="480" alt="per_tag_notification2.jpg" src="https://www.ng.bluemix.net/docs/api/content/services/mobilepush/images/per_tag_notification2.jpg">

2. REST APIを使って、サーバープログラム等から自動的に、アプリにプッシュ通知を送る
<img width="480" alt="PushRESTAPI.png" src="https://qiita-image-store.s3.amazonaws.com/0/75507/812ee563-7213-4aab-0087-f12aec73575b.png">

3. プッシュ通知の送信状況を、Bluemixのダッシュボードから確認する
4. Node-REDからアプリにPush通知する

## APNsやGCMの設定
前提となるAPNsやGCMのファイルは、公式ガイドなどを読んで用意しておく。
- [APNs : Apple Push Notification service](https://www.ng.bluemix.net/docs/services/mobilepush/t_push_config_provider_ios.html)
- [GCM : Google Cloud Messaging](https://www.ng.bluemix.net/docs/services/mobilepush/t_push_config_provider_android.html)

## マニュアルのココが分かりにくいから、気をつけるべし
- Route, App GUID, appSecretが設定に必要な値です。これをダッシュボードのどこに記載されているのか、これが残念な感じに見つかりにくい...。
- SDKをiOSならCocoaPods、AndroidならGradle、HybridならCordova Pluginでアプリに組み込んでビルド
- アプリ側にはRoute, App GUIDを指定
- [REST API](https://mobile.ng.bluemix.net/imfpushrestapidocs/)からプッシュ通知する時には、appSecretを指定

## 必要な設定値は、Bluemixダッシュボードのドコにあるんだ？
というわけで、Route, App GUID, appSecretは、この辺にあります。
![credentials1.png](https://qiita-image-store.s3.amazonaws.com/0/75507/b4e54f4e-1935-e6d9-97dd-20a6bfc456da.png)
"MOBILE OPTIONS"をクリックすると...

![credentials2.png](https://qiita-image-store.s3.amazonaws.com/0/75507/45f48981-397e-1f8c-238a-30b08dacff97.png)
出た！(Route, App GUID)

![credentials3.png](https://qiita-image-store.s3.amazonaws.com/0/75507/ccf1d616-017f-d58d-727d-6eebfb4677a9.png)
Pushの"Show Credentials"の三角をクリックすると...

![credentials4.png](https://qiita-image-store.s3.amazonaws.com/0/75507/0b7f2931-16a9-363e-3205-43df450edd54.png)
出た！(appSecret)

## REST APIで、プログラムからプッシュ通知を送ってみる。(Swaggerベース)
サーバー側のプログラムや別のサービスなどから、プッシュ通知を送信するために、もちろんIMF Pushには、REST APIを公開しているので、これを使う。例えば、行動解析の[Presence Insights](https://console.ng.bluemix.net/catalog/services/presence-insights)サービスでiBeaconのイベントを集めて、アプリにプッシュ通知するとか。自前のRuby, PHP, Node.jsのプログラムからプッシュ通知を送るなどなど・・・。Swaggerベースなので、とりあえずの単体テストや動作確認もココから試せる。地味に便利。

- [IMF Push Service REST API](https://mobile.ng.bluemix.net/imfpushrestapidocs/)

## Node-REDからプッシュ通知する
本来なら、Node-REDのIBM Pushノードから、ほぼ設定不要でプッシュ通知できるところだが、新しくなったばかりのIMFPushに対応していないので、前述のREST APIを応用してNode-REDからプッシュ通知する。とりあえず、Functionの中でAppGUIDとappSecretを設定しておき、前のノードからメッセージ内容を受け取るようにしてみた。
<img width="515" alt="flow.png" src="https://qiita-image-store.s3.amazonaws.com/0/75507/b0ae8410-c43a-9098-babc-a60589c1066f.png">
<img width="606" alt="node_red_func.png" src="https://qiita-image-store.s3.amazonaws.com/0/75507/4f67c42e-0ee3-4018-c4e8-d20eea97c463.png">

```lang:code.js
[{"id":"547bcd10.ab8434","type":"function","z":"7285a9b0.8d7a58","name":"send notification","func":"var AppGUID = 'App GUIDを入力';\nvar appSecret = 'appSecretを入力';\nvar mode = 'SANDBOX'; // 'SANDBOX' or 'PRODUCTION'\n\nvar newmsg = {};\nnewmsg.headers = \n                {'appSecret': appSecret},\n                {'Application-Mode': mode},\n                {'Content-Type':'application/json'};\n\nnewmsg.payload = {\n\t\t\t\t  \"message\" : {\n\t\t\t\t    \"alert\": msg.payload\n\t\t\t\t  }\n                };\n                \nnewmsg.url = 'https://mobile.ng.bluemix.net/imfpush/v1/apps/' + AppGUID + '/messages';\n  \nreturn newmsg;","outputs":1,"noerr":0,"x":286,"y":46,"wires":[["43b67f6a.bc498"]]},{"id":"31a43635.ce5bca","type":"inject","z":"7285a9b0.8d7a58","name":"message","topic":"","payload":"ここにメッセージ入れてね","payloadType":"string","repeat":"","crontab":"","once":false,"x":129,"y":46,"wires":[["547bcd10.ab8434"]]},{"id":"43b67f6a.bc498","type":"http request","z":"7285a9b0.8d7a58","name":"","method":"POST","ret":"txt","url":"","x":273,"y":102,"wires":[["e9dc010e.1624"]]},{"id":"e9dc010e.1624","type":"debug","z":"7285a9b0.8d7a58","name":"","active":true,"console":"false","complete":"payload","x":432,"y":102,"wires":[]}]
```
このフローはいつも通りNode-REDの Import -> ClipboardからコピペすればOK。本家のIBM Pushノードが対応してくれれば、このコードは不要になる。

## サンプルアプリはこちら
GitHubで公開されているのでcloneして、設定値(Route, App GUID)を編集してビルドする。
[iOS](https://github.com/ibm-bluemix-mobile-services/bms-samples-ios-hellopush/)
[Android](https://github.com/ibm-bluemix-mobile-services/bms-samples-android-hellopush/)

## SDKをCocoaPods、Gradle、Cordova Pluginなどでアプリに追加する
サンプルではなく自分のアプリを開発する際には、アプリ側にはSDKを組み込むわけだが、CocoaPodsやGradleでライブラリーを持ってくるのは割と楽。ソースコードには適宜、Route, App GUIDを追記。

iOS : CocoaPods(Podfile)の記述
<pre class="codeblock"><div class="codeAreaWrapper"><div id="codeCopyImgId0" class="codeCopyImg"></div><code class="hljs bash"><span class="hljs-built_in">source</span> <span class="hljs-string">'https://github.com/CocoaPods/Specs.git'</span>
<span class="hljs-comment"># Copy the following list as is and remove the dependencies you do not need</span>
pod <span class="hljs-string">'IMFCore'</span>
pod <span class="hljs-string">'IMFPush'</span></code></div></pre>

Android : Gradle(build.gradle)の記述
<pre class="codeblock"><div class="codeAreaWrapper"><div id="codeCopyImgId0" class="codeCopyImg"></div><code class="hljs cs">dependencies {
  compile <span class="hljs-string">'com.ibm.mobilefirstplatform.clientsdk.android:push:1.+'</span> 
  compile <span class="hljs-string">'com.google.android.gms:play-services:7.8.0'</span> 
}  </code></div></pre>

Hybrid : Cordova Pluginの記述
<pre class="codeblock"><div class="codeAreaWrapper"><div id="codeCopyImgId1" class="codeCopyImg smallCopyImg"></div><code class="hljs">cordova plugin add ibm-mfp-push</code></div></pre>

## まとめ
基本的には公式ガイドに全部書いているので、Route, App GUID, appSecretが設定に必要な値であることが分かれば、あとはSwaggerが使えるREST APIでテスト的にプッシュ通知して疎通確認。もちろんダッシュボードはユーザーフレンドリーなので、開発者じゃないヒトはこちらを使うと思う。あと、Node-REDの[Pushノード:node-red-ibmiotpush](http://flows.nodered.org/node/node-red-ibmiotpush)が未対応になってたので、IMFPushに対応完了するまでは、HTTP Requestでこのプッシュ通知は実装することになる。[公式ガイド](https://www.ng.bluemix.net/docs/#services/mobilepush/index.html)