NCMBのFlutter SDKを使ってプッシュ通知を送信する（iOS編）

NCMBのコミュニティSDK（公式サポートは提供されていません）としてFlutter向けのSDKを提供しています。Flutter SDKはiOS/Androidはもちろんのこと、Webなどでも利用できます。つまりスマートフォンネイティブの機能は提供していません。

NCMBのプッシュ通知機能は数多くの方に使われている機能でもあり、今回はFlutter SDKを使ってどうプッシュ通知機能を使えば良いのかを紹介します。まずはiOS編です。

[ncmb | Dart Package](https://pub.dev/packages/ncmb)

## 利用するライブラリ

上述の通り、Flutter SDKにはネイティブ機能がありませんので、プッシュ通知で利用するデバイストークンを取得する機能がありません。そこで下記のライブラリを使います。

- [push | Flutter Package](https://pub.dev/packages/push)

## セットアップ

iOSの場合はiOS Dev Centerにてアプリを登録し、Push Notificationを有効にします。Keysのところでプッシュ通知を有効にすると、p8ファイルがダウンロードできます。

![4dd91ba8-f96a-454a-86aa-a886fd02b310.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/55fe5921-22e4-d6c0-8c9f-77c13ad63b40.jpeg)

アプリのバンドルID、チームID、p8ファイル、AppleキーIDを取得したら、NCMBの管理画面でそれぞれ設定します。アプリのバンドルIDはAppleトピックIDとして設定してください。

![ebe93836-fd88-4cc5-a2a2-139dcb2ec1ce.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/813248a0-02a1-1479-799a-caacf75c74e4.jpeg)


## Flutterアプリの作成

`flutter create アプリ名 --org 組織` でアプリを作成します。iOSの場合は組織を指定しなくても大丈夫そうですが、Androidはコードが入ったフォルダ構成などにも影響するので、指定した方が良さそうです。

## Xcodeの設定

`ios/Runner.xcworkspace` を開いて、Capabilitiesでプッシュ通知を有効にします。

## ライブラリの追加

`flutter` コマンドでライブラリを追加します。

```
flutter pub add ncmb
flutter pub add push
```

## main.dartの編集

### ライブラリのインポート

追加したライブラリを読み込みます。

```dart
import 'package:push/push.dart';
import 'package:ncmb/ncmb.dart';
```

main関数でNCMBを初期化します。

```dart
NCMB("YOUR_APPLICATION_KEY",
      "YOUR_CLIENT_KEY");
```

### デバイストークンの登録

適当なボタンを配置して、デバイストークンの取得を行う関数を呼び出します。

```dart
TextButton(onPressed: getToken, child: const Text("プッシュ通知を受け取る"))
```

![IMG_0907.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/9fd58f21-4695-ac4a-f2f3-f75a3c9c33e1.png)


getToken関数の内容です。

```dart
void getToken() async {
	var token = await Push.instance.token;
	if (token != null) {
		saveToken(token)
		setState(() {
			_deviceToken = token;
		});
	}
}
```

そして saveToken 関数でデバイストークンをNCMBへ保存します。deviceTokenとdeviceTypeは必須です。

```dart
void saveToken(String token) async {
	try {
		var installation = NCMBInstallation();
		installation
			..set("badge", 0)
			..set("deviceToken", token)
			..set("deviceType", Platform.isIOS ? "ios" : "android");
		await installation.save();
	} catch (e) {
		debugPrint("エラー ${e.toString()}");
	}
}
```

ちゃんと保存できていれば、NCMBの管理画面でInstallationクラスにデータが追加されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/71d58dd7-e1b4-b7a7-9013-9babbbde711d.png)


これでプッシュ通知の送信準備が整いました。

## プッシュ通知を送信する

NCMBの管理画面でプッシュ通知を送信します。送信先としてiOSを選んでください。

## プッシュ通知を受け取る

プッシュ通知を受け取るとイベントが呼ばれるので、initStateで定義します。

```dart
@override
void initState() {
	super.initState();
	Push.instance.onNotificationTap.listen((data) {
		// アプリは起動中で、プッシュ通知を開いた場合
	});
	Push.instance.notificationTapWhichLaunchedAppFromTerminated.then((data) {
		// アプリが終了していた場合
		if (data == null) {
			// アプリ起動時
		} else {
			// 通知を開いた場合
		}
	});
	Push.instance.onMessage.listen((message) {
		// アプリがフォアグラウンド
	});
	Push.instance.onBackgroundMessage.listen((message) async {
		// アプリがバックグラウンド
	});
}
```

messageは次のような内容になっています。dataはこの中のmessage.dataに該当します。dataはプッシュ通知の内容がMapで入っています。

- message.notification（通知オブジェクト）
	- message.notification?.title.toString() （通知タイトル）
	- message.notification?.body.toString() （通知本文）
	- message.data ペイロード

例えばmessage.dataは次のようになります。

```json
{
	"com.nifcloud.mbaas.PushId": "UgGJ9dz9KQ7mGmjZ",
	"aps": {
		"alert": {
			"title": "プッシュ通知テスト",
			"body": "これはFlutterアプリ向けのプッシュ通知です。"
		}, 
		"sound": "default"
	}
}
```

![IMG_0910.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/22f1212c-5c63-a33d-30e7-f3c5fe351f1b.png)


## まとめ

iOSのプッシュ通知は比較的簡単に実装できます。プッシュ通知を開いた後の動作については、dataの内容を見て判別すれば良いでしょう。他にもJSONやURLも送れますので、活用してください。