【Monaca】サイレントプッシュ通知でペイロードを受け取る方法

# 動作確認サンプル

Monaca から ニフクラ mobile backend を使った基本のプッシュ通知配信方法は既知として説明は割愛します。プッシュ通知配信に必要な証明書（p12）または設定ファイル（json）の作成方法は各自対応をお願いします。

 （参考）iOSの場合：[プッシュ通知に必要な証明書の作り方 \- Qiita](https://qiita.com/natsumo/items/d5cc1d0be427ca3af1cb)

## 動作検証環境

* Monaca Cordovaバージョン（CLIバージョン） 7.1.0
* Monaca プラグイン NIFCloudMB（ncmb-push-monaca-plugin）　3.0.2
* 検証端末 iPhone6 iOS 12.4.5

## サンプルアプリの作成手順
### ニフクラ mobile backend 側作業

* アプリを新規作成してAPIキーを確認する
* 設定から「プッシュ通知を許可」する
* 証明書（p12）または設定ファイル（json）を設定する

### Monaca側作業

* 「最小限のテンプレート」でプロジェクトを作成する
* `index.html` を以下のコードに書き換える

```html:index.html
<!DOCTYPE HTML>
<html>
<body>
	<br />
    <h2>プッシュ通知配信テスト用</h2>
    installation登録状況：<span id="result1">-</span><br/>
    <input type="button" onClick="getInstallationId()" value="getInstallationID" />
    ：<span id="installationID">-</span><br/>
    JSON：<br/>
    <textarea id="result2" style="width:100%;"></textarea>
</body>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: content: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
        document.addEventListener("deviceready", function(){
            // プッシュ通知受信時のコールバックを登録します
            window.NCMB.monaca.setHandler(function(jsonData){
                // 送信時に指定したJSONが引数として渡されます
                document.getElementById("result2").innerText = JSON.stringify(jsonData);
            });

            var successCallback = function () {
                //端末登録後の処理
                document.getElementById("result1").innerText = "Success";
            };
            var errorCallback = function (err) {
                //端末登録でエラーが発生した場合の処理
                document.getElementById("result1").innerText = "Error: " + err;
            };
            // デバイストークンを取得してinstallation登録が行われます
            window.NCMB.monaca.setDeviceToken(
                "YOUR_NCMB_APPLICATION_KEY",
                "YOUR_NCMB_CLIENT_KEY",
                successCallback,
                errorCallback
            );
        },false);

        function getInstallationId() {
            // 登録されたinstallationのobjectIdを取得します。
            window.NCMB.monaca.getInstallationId(function(id) {
                document.getElementById("installationID").innerText = id;
            });
        }
    </script>
</head>
</html>
```

* L.39,40を mobile backend のAPIキーに書き換える
  * `YOUR_NCMB_APPLICATION_KEY` 
  * `YOUR_NCMB_CLIENT_KEY`
* プラグインを２つ有効化する
  * NIFCloudMB
  * Notification ※ペイロード受信の確認のため使用
* iOS端末で動作確認する場合＞証明書(cer)とプロビジョニングプロファイルを設定する
* iOS端末で動作確認する場合＞AppIDをプロビジョニングプロファイルに合わせて設定する
* ビルドする

### 端末（アプリ）側作業

* ビルドしたプロジェクトを端末にダウンロードする
* ダウンロードしたアプリを起動する
* プッシュ通知の受信可否確認のポップアップが表示されたら必ず「__許可__」しておく
* 画面を確認する
  * 「installation登録状況」が「Success」ならプッシュ通知の配信準備完了です
  * 「getInstallationID」をタップするとニフクラ mobile backend のデータストアに格納されたinstallationIDのobjectIdが表示されます
  * 「JSON」は空欄ですが、ここに後ほど取得したペイロード情報（json）が記載されます

<img width=300px" alt="IMG_0004.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112032/7732011d-3f43-ba13-f4cd-2b94abd338cf.png">

## 配信から受け取りまでの手順
### ニフクラ mobile backend でペイロード付きサイレントプッシュ通知を配信する

* 「タイトル」、「メッセージ」を__空欄__にすることでサイレントプッシュ通知を配信できます
* 「JSON」に入力した内容をペイロードとして端末で取得することができます
  * keyを`data`としてJSONを記載します 例） `{"data":"Hello,NCMB!"}`

<img width="500" alt="スクリーンショット 2020-03-02 13.59.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112032/f86f205e-f3f5-7457-f312-68ff03e2446a.png">

* iOS端末で動作確認する場合＞「音声ファイル名」の「default」を削除する（空欄にする）
* iOS端末で動作確認する場合＞「content-available」を有効にする

<img width="500" alt="スクリーンショット 2020-03-02 14.00.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112032/aa2958a3-2a36-8b5a-86e6-2dcf06b0ffa4.png">

* プッシュ通知を配信する

### Monacaでサイレントプッシュ通知を受信してペイロードを取得する

* 「アプリを起動した状態（フォアグラウンド）」でのみペイロードを受信できます
* 受信するとペイロードが「JSON」に表示されます

<img width="300" alt="IMG_0006.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112032/1cd4d36c-7e45-d8ef-15c4-40f9cd0bc6b8.png">

## 参考

「アプリを起動した状態（**バックグラウンド**）」でペイロードを受信したい場合は、background処理ができるプラグインを有効化して、次にように実装します。

* プラグイン： https://github.com/transistorsoft/cordova-plugin-background-fetch
  * zipをダウンロードして「Cordovaプラグインのインポート」から設定
  * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112032/993c3b9d-0387-9233-8b06-f11afd6feb0e.png)


```js
document.addEventListener("deviceready", function(){
    // プッシュ通知受信時のコールバックを登録します
    window.NCMB.monaca.setHandler(function(jsonData){
        // 送信時に指定したJSONが引数として渡されます
        document.getElementById("result2").innerText = JSON.stringify(jsonData);
    });

    var successCallback = function () {
        //端末登録後の処理
        document.getElementById("result1").innerText = "Success";
    };
    var errorCallback = function (err) {
        //端末登録でエラーが発生した場合の処理
        document.getElementById("result1").innerText = "Error: " + err;
    };
    // デバイストークンを取得してinstallation登録が行われます
    window.NCMB.monaca.setDeviceToken(
        "YOUR_NCMB_APPLICATION_KEY",
        "YOUR_NCMB_CLIENT_KEY",
        successCallback,
        errorCallback
    );
    /* ★以下追記 */
    // バックグラウンド処理
    var BackgroundFetch = window.BackgroundFetch;

    // Your background-fetch handler.
    var fetchCallback = function(taskId) {
      // プッシュ通知受信時のコールバックを登録します
      window.NCMB.monaca.setHandler(function(jsonData){
          // 送信時に指定したJSONが引数として渡されます
          document.getElementById("result2").innerText = JSON.stringify(jsonData);
      });
      document.getElementById("result3").innerText = '[js] BackgroundFetch event received: ' + taskId;
      // Required: Signal completion of your task to native code
      // If you fail to do this, the OS can terminate your app
      // or assign battery-blame for consuming too much background-time
      BackgroundFetch.finish(taskId);
    };

    var failureCallback = function(error) {
      document.getElementById("result3").innerText = '- BackgroundFetch failed: '+ error;
    };

    BackgroundFetch.configure(fetchCallback, failureCallback, {
      minimumFetchInterval: 15 // <-- default is 15
    });
},false);

function getInstallationId() {
    // 登録されたinstallationのobjectIdを取得します。
    window.NCMB.monaca.getInstallationId(function(id) {
        document.getElementById("installationID").innerText = id;
    });
}
```