🤖

Firebase Admin SDKを使用せずに、サーバーサイドDartからプッシュ通知を送信する🐶

2022/11/26に公開約2,000字

経緯

深い理由はないですが、サーバーサイドDartからプッシュ通知を送る方法はないかな🤔?と思い、調べてみましたので備忘録として書きます。
(DartのAdmin SDKそろそろあってもいいですよね...)

方法

準備

Firebaseのプロジェクトを用意してください。Firebaseのセットアップ方法は割愛します。
プロジェクトの設定 -> サービスアカウント -> 新しい秘密鍵の生成でjsonファイルを生成できますので、大切に保管してください。

利用するパッケージ

以下3つのパッケージを利用します。

  • http
  • googleapis
  • googleapis_auth

https://pub.dev/packages/http
https://pub.dev/packages/googleapis
https://pub.dev/packages/googleapis_auth

書く

先ほど生成した秘密鍵の中身から必要な値は次の5つです。
private_key_id, private_key, client_email, client_id, type

また、プロジェクトIDも必要になります。プロジェクトIDは
プロジェクトの設定 -> 全般 -> プロジェクトIDに記載されています。

これらの値を.envなどから読み取れるようにしておき、送り先のトークンを準備して、以下のように書くとDartでプッシュ通知を送信することができました🐶

import 'package:googleapis/fcm/v1.dart';
import 'package:googleapis_auth/auth_io.dart';
import 'package:http/http.dart' as http;

Future<void> sendMessage() async {
  final client = http.Client();
  
  // dotenvなどを利用すると良いと思います。
  final accountCredentials = ServiceAccountCredentials.fromJson({
    'private_key_id': PRIVATE_KEY_ID,
    'private_key': PRIVATE_KEY,
    'client_email': CLIENT_EMAIL,
    'client_id': CLIENT_ID,
    'type': 'service_account' // ここはみんな一緒
  });

  final authClient = await clientViaServiceAccount(
    accountCredentials,
    [FirebaseCloudMessagingApi.firebaseMessagingScope],
    baseClient: client,
  );

  final api = FirebaseCloudMessagingApi(authClient);

  try {
    final message = await api.projects.messages.send(
      SendMessageRequest(
        message: Message(
          token: 'MESSAGE_TOKEN', // 宛先のトークンを入れてください
          notification: Notification(
            title: 'TITLE',
            body: 'BODY',
          ),
        ),
      ),
      'projects/$PROJECT_ID',
    );

    print(message.toJson());
  } on ApiRequestError catch (e) {
    // 無効なトークンを使用するなど、失敗した場合はApiRequestErrorがThrowされます。
    // ApiRequestErrorという名前ですがExceptionクラスです。
    print(e);
  } finally {
    client.close();
  }
}

終わりに

googleapisgoogleapis_authはExampleがあまり充実してない...ので、ソースコード辿ったりしましたが、なんとかできました。
実際はCloud Functionsを利用することが多いと思うので、あまり出番はないかもしれませんが、一応選択肢はあるんだなー程度に。

Discussion

ログインするとコメントできます