---
# System prepended metadata

title: "FirebaseAdmin SDK For\_.NET - FCM篇"

---

# FirebaseAdmin SDK For .NET - FCM篇
###### *透過FCM 對行動裝置發送推播通知吧!*

### 前言:
> *Q: Firebase Admin SDK是什麼?*

Admin SDK是一組服務器庫，可以從特權環境與Firebase 進行交互，以執行以下操作：
* 以完整管理員權限讀寫Realtime Database 數據。
* 使用簡單的替代方法以編程方式將Firebase Cloud Messaging 消息發送至Firebase Cloud Messaging 服務器協議。
* 生成並驗證Firebase 身份驗證令牌。
* 訪問Google Cloud 資源，例如與Firebase 項目相關聯的Cloud Storage 和Cloud Firestore 資料庫。
* 創建自己的簡化管理控制台，以執行用戶數據查詢或更改用戶的身份驗證電子郵件地址等操作。

> *本篇文章將著重在Firebase Cloud Messaging(FCM) 服務*

Firebase Cloud Messaging (FCM)
(FCM) 是一種跨平台消息傳遞解決方案，可以通知客戶端應用有新的電子郵件,或其他數據有待同步；
透過發送通知消息進行用戶再互動,一條消息可將最多4000 字節的載荷傳送至客戶端應用。

---

### **開發環境與安裝**

##### 開發環境:
>  Admin .NET SDK - .NET Framework 4.6.1+ 或適用於.Net Core 2.0+ 的.NET Standard 2.0
 
##### FirebaseAdmin For .NET 安裝方法
> 1. 使用 .NET CLI
> `dotnet add package FirebaseAdmin - version 2.3.0`
> 2. 使用 套件管理器控制台
> `NuGet\Install-Package FirebaseAdmin -Version 2.3.0`

*如需對服務帳號進行身份驗證並授予其訪問Firebase 服務的權限，必須生成JSON 格式的私鑰文件*

##### 生成私鑰文件

在 [Firebase控制台](https://console.firebase.google.com/)中，選擇專案>打開設置>服務帳號。點擊生成新的私鑰，然後點擊生成密鑰進行確認。

![](https://i.imgur.com/yvrODvP.jpg)


產出的Json 文件格式會看起來像是:

> ex: serviceAccountKey.json
```json=
{
   "type": "service_account",
   "project_id": "專案id",
   "private_key_id": "私鑰id",
   "private_key": "-----BEGIN PRIVATE KEY-----\私鑰本人\n-----END PRIVATE KEY-----\n",
   "client_email": "Email",
   "client_id": "客戶端id",
   "auth_uri": "https://accounts.google.com/o/oauth2/auth",
   "token_uri": "https://oauth2.googleapis.com/token",
   "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
   "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-blablabla-android.iam.gserviceaccount.com"
}
```



### **開始使用**

##### 初始化Firebase服務

在Constructure 中初始化Firebase 並產生出憑證,
缺少這一步可能會導致在傳送資料至Firebase 服務器時報錯
>  NotifyService.cs
```csharp=
// NotifyService Constructure
public NotifyService(IServiceProvider provider) : base(provider)
{
   // 當找不到firebase實體時,重新初始化產出憑證
   if (FirebaseApp.DefaultInstance == null)
   {
       FirebaseApp.Create(new AppOptions()
       {
          Credential = GoogleCredential.FromFile("path/to/serviceAccountKey.json"),
       });
   }
}
```
無論是哪個平台，所有應用實例都可以解讀以下通用字段：
* message.notification.title
* message.notification.body
* message.data

##### 向單一特定裝置發送通知
 ```csharp=
/// <summary>
 /// 向單一特定裝置發送通知
 /// </summary>
 /// <param name="notifyToken">已驗證的Notify Token</param>
 /// <returns></returns>
 public async Task SendNotify(string notifyToken)
 {
    var message = new Message()
    {
       Notification = new Notification()
       {
         Title = "推播測試",
         Body = "通用平台之單一裝置推播測試"
       },
       Token = notifyToken
    };

    // 向該裝置發送推播
    string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);

    Console.WriteLine("發送推播成功: " + response);
 }
```
註解:
> "Message" 是 Firebase Cloud Messaging (FCM) 中用於發送通知的一個類別，它包含了各種用於定義推播訊息內容的屬性。
> "Notification"是指在行動裝置的訊息列（notification drawer）中顯示的訊息。程式碼中的 Notification()是一個 C# 物件，用於設定要發送的通知的標題和內容。

##### **使用針對具體平台的字段**

使用時機
* 僅向特定平台發送字段
* 發送通用字段以及針對具體平台的字段

> 如果僅希望向特定平台發送值時，"不要"使用通用字段，而應使用針對具體平台的字段。
> 例如，如需僅向Apple 平台和Web 發送通知，而不向Android 發送通知，必須針對Apple 和Web 各使用一組字段

ex: 個別向安卓與IOS發送不同的推播設定
> NotifyService.cs

```csharp=
/// <summary>
/// 分別向Android與IOS發送不同設定的推播
/// </summary>
/// <param name="notifyToken"></param>
/// <returns></returns>
public async Task SendNotify2(string notifyToken)
{
   var message = new Message
   {
      Notification = new Notification()
      {
         Title = "推播測試",
         Body = "依照設備推播不同的設定",
      },
      // 為Android目標設備設定樣式或是時間...等等
      Android = new AndroidConfig()
      {
         TimeToLive = TimeSpan.FromHours(1),
         Notification = new AndroidNotification()
         {
            Icon = "stock_ticker_update",
            Color = "#f45342",
         },
      },
      // 為IOS目標設備設定應用程序圖標右上角的紅色圓形數字提醒
      Apns = new ApnsConfig()
      {
         Aps = new Aps()
         {
             Badge = 42,
         },
      }
   };

   // 向設備發送推播
   string response = await FirebaseMessaging.DefaultInstance.SendAsync(message2);

   Console.WriteLine("發送推播成功: " + response);
}
```
註解:
>  Badge Notification是指出現在App圖標右上角的紅色圓形數字提醒，用於提醒一些無需即時處理的消息，比如程序更新數、未讀郵件數等。
> 向多台裝置發送消息![](https://i.imgur.com/jsisbPP.jpg)

##### 發送訊息給多個裝置

***將消息推播到多個裝置。每次調用時，最多可以指定"500個" 裝置註冊令牌***

ex: 向多個裝置發送訊息
> NotifyService.cs
```csharp = 
/// <summary>
/// 向多個裝置發送推播
/// </summary>
/// <returns></returns>
public async Task SendNotifyToMultiDevice()
{
    // These registration tokens come from the client FCM SDKs.
    var registrationTokens = new List<string>()
    {
        "TOKEN_1",
        "TOKEN_2",
        // ...
        //一個 Batch最多有500筆Token
        "TOKEN_500",
    };

    var message = new MulticastMessage()
    {
        Tokens = registrationTokens,
        Data = new Dictionary<string, string>()
        {
            { "platform", "通用平台" },
            { "object", "多個裝置" }
        },
    };

    var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(message);
    
    //檢查發送失敗的Token
    if (response.FailureCount > 0)
    {
        var failedTokens = new List<string>();
        for (var i = 0; i < response.Responses.Count; i++)
        {
            if (!response.Responses[i].IsSuccess)
            {
                //將失敗的Token加入至List裡
                failedTokens.Add(registrationTokens[i]);
            }
        }
        Console.WriteLine($"失敗的Token List: {failedTokens}");
    }
}
```
##### **Data 和 CustomData 的區別**

在 FCM 中，Data 和 CustomData 都是用來傳遞自訂資料的機制，但它們在傳遞資料的方式上有些微的差別

1. *Data*：是 FCM 的一個內建的機制，用來傳遞 key-value pair 的資料。當手機端收到訊息時，這些資料會透過 Intent 傳遞給應用程式。
1. *CustomData*：顧名思義，就是使用者自行定義的資料，可以是任何格式的資料，例如 JSON、XML 等等。CustomData 是透過傳送 payload 的方式，讓 FCM 將資料原封不動地轉發給設備端應用程式。

ex: 向多個IOS裝置發送訊息
> NotifyService.cs
```csharp=
 /// <summary>
 /// 向多個IOS裝置發送推播
 /// </summary>
 /// <param name="tokenList">IOS裝置Token List</param>
 /// <returns></returns>

 public async Task SendNotifyToMultiIOS(List<string> tokenList)
 {
     var message = new MulticastMessage()
     {
         Tokens = tokenList,
         Apns = new ApnsConfig()
         {
             Aps = new Aps()
             {
                 Alert = new ApsAlert()
                 {
                     Title = "FirebaseAdmin SDK For .NET",
                     Body = "本篇文章透過Firebase 服務中的FCM 實作對行動裝置發送推播通知"
                 },
                 Badge = 1,
                 Sound = "default"
             },
             CustomData = new Dictionary<string, object>()
             {
                   { "platform", "IOS" },
                   { "devices", "多個裝置" }
             }
         }
     };

     await FirebaseMessaging.DefaultInstance.SendMulticastAsync(message);
 }
```

---

### 結論
透過FCM 我們可以對裝置發送推播訊息,也可以針對不同的裝置發送不同格式的Notify,Firebase Admin不只是提供了Clound Messaging,還有Authentication ,Real Time的資料庫,Analytics 提供事件報告幫助了解用戶與應用進行互動,還有許多與Google相關的功能。

未來有機會再跟大家介紹 ❤️❤️