[Lambda][FCM]LambdaからFlutterアプリに向けたPush通知を実行する


FCM経由でFlutterアプリにPush通知を送るにあたり、Lambda（それもPython）を使った記事が少ないと感じたので投稿します。

## はじめに

FCMコンソール側の設定・Flutterアプリ側の実装は世の中にHowToが溢れているので割愛します。

https://firebase.google.com/docs/cloud-messaging?hl=ja

https://firebase.google.com/docs/cloud-messaging/flutter/client?hl=ja

LambdaでFirebase Admin SDKを使用した、Push通知送信リクエスト実行方法のみ記載したいと思います。
なんでわざわざLambdaなのかと言われると、単にAWSで他のサービスを利用しているため選択肢に挙がったまでです。

![スクリーンショット 2024-01-05 16.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661825/d7be1d85-b859-b78f-0df2-e0c0b0c14ee0.png)



## 前提条件

①Flutterアプリ側でFCMからエンドポイントを取得済（Flutterアプリ側以下のソースで取得できます）
````dart
final fcmToken = await FirebaseMessaging.instance.getToken();
````
https://firebase.google.com/docs/cloud-messaging/flutter/client?hl=ja#access_the_registration_token


②Firebaseコンソール>Firebaseプロジェクトの設定>サービスアカウントより、秘密鍵を取得済

`serviceAccountKey.json`という名前でダウンロードされます。

https://firebase.google.com/docs/cloud-messaging/auth-server?hl=ja#provide-credentials-manually


## ①Lambda Layerの作成

Lambda Layerとは、複数のLambda関数に適用が可能な共有ロジックのようなものです。
Firebase Admin SDKを包含するLayerを作成し、それをLambda関数に読み込ませるために作成します。

**▼Firebase Admin Python SDKの取得**
今回はPythonで実行環境を作ります。

````
sudo pip install firebase-admin
````

あるいはサイトからダウンロードもできます

https://pypi.org/project/firebase-admin/

インストールしたディレクトリを
python/firebase-admin/という構成にしてzipにします。
※Lambda Layerでは読み込めるファイルのパスが決まっているため

**▼Layerの新規作成**



![スクリーンショット 2024-01-05 17.35.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661825/cbc955f1-69c2-6b9c-47a0-27e525b602e1.png)

AWS Lambdaに移ります。
サイドバーの[レイヤー]→[レイヤーの作成]→.zip ファイルをアップロードで先ほど作成したfirebase-admin が内包されたzipファイルをアップロード
また、互換性のあるランタイムに任意のPythonバージョンを追加します。

今回は`firebase_admin_layer`という名前にしました。

![スクリーンショット 2024-01-05 18.06.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661825/57369bf0-d9e5-5f68-3f03-f9668779ade8.png)

これでLayerの作成は完了

## ②Lambda 関数の作成

**▼Lambda 関数の準備**

引き続き、AWS Lambdaです。
サイドバーの[関数]→[関数の作成]→[一から作成]を選択
ランタイムを任意のPythonバージョンに設定します。

作成した関数を開き、[コード]タブの一番下
レイヤーを設定する項目があります。

![スクリーンショット 2024-01-05 17.45.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661825/aaa70db4-8e66-e5c7-e65d-7bcb819d8dc2.png)

[レイヤーの追加]→[カスタムレイヤー]から、①で作成したLayerを選択します

設定周りはこれで完了

**▼コードの作成**

Lambda関数でのコードの作成に移ります。
Push通知送信リクエストです。

lambda_function.pyの内容を以下にベタ貼りします。
※動作確認済

````python

import firebase_admin   # Layerを追加しているためfirebase_admin SDKが使用できる
from firebase_admin import credentials
from firebase_admin import messaging

##デバイスに通知を送る
def lambda_handler(event, context):
    
    if not firebase_admin._apps:
        cred = credentials.Certificate("serviceAccountKey.json") #事前準備②
        firebase_admin.initialize_app(cred)
    
    
    # This registration token comes from the client FCM SDKs.
    registration_token = "エンドポイントが入ります" #事前準備①

    
    # See documentation on defining a message payload.
    
    message = messaging.Message(
        notification=messaging.Notification(
            title='test server',
            body='test server message',
            
        ),
        token=registration_token,
    )
    
    # Send a message to the device corresponding to the provided
    # registration token.
    response = messaging.send(message)
    
    # Response is a message ID string.
    print('Successfully sent message:', response)

````


`lambda_function.py`と同一の階層に`serviceAccountKey.json`という名前でファイルを新規作成し、事前準備②でダウンロードした秘密鍵の内容をそのままペーストしすべての準備OK




## 動作確認

Lambda関数を実行すると、エンドポイントに紐づくアプリにPush通知が表示されます
これにて送信リクエスト成功。

Lambda関数の設定で[関数 URL を有効化]すれば、少ない修正でAPI化できますね。
もちろんAPI Gatewayを使うのもよし。

仕事でPush通知に関してはかなり調査したので、また記事にしたいですねえ


## 参考

https://firebase.google.com/docs/cloud-messaging?hl=ja

https://firebase.google.com/docs/cloud-messaging/flutter/client?hl=ja

https://firebase.google.com/docs/admin/setup?hl=ja


https://qiita.com/kousaku-maron/items/23d88b26c8a1cd0b1140

https://qiita.com/hirai-11/items/4acb61bede53805c1527