GCMのUser Notificationsの使い方

※本記事は[WaterCell Developer's Blog](http://watercelldev.hatenablog.jp/entry/2014/10/22/145223)からの転載です。

[Google Cloud Messaging for Android](https://developer.android.com/google/gcm/index.html)の勉強をしていたところ、User Notificationsのドキュメントに分かりづらい部分があってハマったので、備忘録として書き残しておこうと思います。

というわけで、User Notificationsがどんな機能なのかは説明しません。知りたい方は、ドキュメントをお読みください。

### User Notificationsを使わずにpush配信する

まずは、普通のpush配信のやり方。公式資料でも丁寧に紹介されていますし、日本語記事も多くあります。

* [GCM HTTP Connection Server | Android Developers](https://developer.android.com/google/gcm/http.html)
* [[改訂版]Google Cloud Messaging (GCM) でプッシュ配信する[Android] ｜ Developers.IO](http://dev.classmethod.jp/smartphone/android/gcm/)

```
curl \
--header "Authorization: key=<API_KEY>" \
--header Content-Type:"application/json" \
https://android.googleapis.com/gcm/send \
-d "{\"registration_ids\":[\"<REGID>\"],\"data\":{\"message\":\"Hello\"}}"
```

`registration_ids`をJSON配列として列挙すれば、IDに紐付いた端末に`{"message":"Hello"}`というデータが配信されます。

### User Notificationsを使ってpush配信する

同じユーザーが持っている複数の端末に対してPush通知を送りたい場合は、`registration_ids`を列挙するよりも、User Notificationsを使ったほうが便利そうです。

* [User Notifications | Android Developers](https://developer.android.com/google/gcm/notifications.html)

シンプルな流れとしては、下記の手順になります。

1. 複数の`registration_id`をまとめた`notification_key`を発行する
2. `notification_key`を使ってpush通知を行う

#### notification_keyを発行する

まずは`notification_key`を発行しましょう。各種ID, KEYを適切に配置していけば、特に難しいことはありません。

Request

```
curl \
--header "project_id: <PROJECT_NUMBER>" \
--header "Authorization: key=<API_KEY>" \
--header Content-Type:"application/json" \
https://android.googleapis.com/gcm/notification \
-d "{\"operation\": \"create\",\"notification_key_name\": \"appUser-Hogehoge\",\"registration_ids\":[\"<REGID>\",\"<REGID>\",\"<REGID>\"]}"
```

Response

```
{"notification_key":"<NOTIFICATION_KEY>"}
```

上記のようなリクエストを送ることで、無事に`notification_key`を取得できました。

#### push通知を行う（仮）

それでは、`notification_key`を使って実際にpush通知を行ってみます。

* [Implementing GCM Server | Android Developers](https://developer.android.com/google/gcm/server.html)

`registration_ids`の説明を見ると、必須項目についての話題がありました。

> A request must include a recipient—this can be either a registration ID, an array of registration IDs, or a `notification_key`. Required.

`registration_ids`か`notification_key`のどちらかを必須で含めればよいようです。ということは`registration_ids`を使ったパターンをそのまま差し替えればいけるはず。

Request

```
curl \
--header "Authorization: key=<API_KEY>" \
--header Content-Type:"application/json" \
https://android.googleapis.com/gcm/send \
-d "{\"notification_key\":\"<NOTIFICATION_KEY>\",\"data\":{\"message\":\"Hello\"}}"
```

Response

```
Missing "registration_ids" field
```

・・・あれっ？

#### 困ったときのStackOverflow

StackOverflowを探してみると同じ悩みを持った人が見つかりました。

* [android - GCM User Notifications: Missing "registration_ids" field - Stack Overflow](http://stackoverflow.com/questions/19720767/gcm-user-notifications-missing-registration-ids-field)

ベストアンサーがこちらになります。

> The documentation is buggy, you have to use this request:

```
// 略
{ 
   "to": "<NOTIFICATION-ID>",
   "data": {},
}
```

**`notification_key`の記述には`to`を使うそうです。** 

この回答者の方はドキュメントのバグと言ってますが、現在のドキュメントを改めて見てみたところ、`notification_key`の行の端にこんな記述がありました。

> HTTP. This feature is supported in CCS, but you use it by specifying a notification key in the "to" field.

* [Message Parameters](https://developer.android.com/google/gcm/server.html#params)

なるほど、`notification_key`フィールドがサポートされているのはCCS方式でリクエストするときだけで、あとの場合は`to`に入れてねということでしょうか。

しかしこの書き方だと、結局サポート先がHTTPなのかCCSなのか分かりづらいですね。また、当の`to`の行を見ると、CCSのみのサポートでHTTPはサポートしていないことになっているので、なるほどこれはbuggyと言われても仕方がない感じがします。

#### push通知を行う（真）

そんなわけで、最終的に`notification_key`を付与したリクエストは、下記の形になりました。

```
curl \
--header "Authorization: key=<API_KEY>" \
--header Content-Type:"application/json" \
https://android.googleapis.com/gcm/send \
-d "{\"to\":\"<NOTIFICATION_KEY>\",\"data\":{\"message\":\"Send with User Notification\"}}"
```

手元の端末が一斉に震える様は壮観でした。

### まとめ

GCMを触り始めてみて、push通知が思ったより簡単に、そして無料でできることに驚いています。

ほしい情報をほしい時に通知する、という理想を実現するためには、push通知は大きな役割を果たしてくれます。Android Wearな腕時計型デバイスやGoogle Glassなど、アプリからの通知を受け取ってユーザーの見やすい場所に表示してくれる強力なツールも今後増えていくことでしょう。

通知周りはまたしばらく勉強していきたいと思います。

### 宣伝

[ウォーターセル株式会社](http://water-cell.jp/)では、農業生産者に嬉しい情報の扱い方を一緒に考えてくれるAndroidアプリエンジニア、インフラエンジニア、Webフロントエンドエンジニア、Railsエンジニアを探しています。

興味のある方は、是非ご一報ください。