[料理佳餚] Xamarin.Forms(iOS)接收來自 Firebase Cloud Messaging 的推播通知

上一篇 Xamarin.Forms(Android)接收來自 Firebase Cloud Messaging 的推播通知,當然也要來個 iOS 版本,但是在這個過程當中走了相當多的坎坷路,才知道原來 iOS 模擬器不能模擬東西還不少,為了開發 iOS App 除了買 Mac 用來建置之外,還得買 iPhone 來測試模擬器不能測試的東西,還要為我們的開發者帳號繳至少一年 $99 鎂的費用,著實花了不少錢,說這些都是淚水啊。

將 Firebase 加入您的 iOS 應用程式

建立 Firebase 專案的部分就參考 Android 版本的那篇文章就可以了,我就直接在原本的專案上連結 iOS 應用程式。

除了 iOS 繫結 ID(BundleIdentifier)之外其他為選填,繫結 ID 不要亂取,之後在 iOS App 上也要根據這個繫結 ID 來做一些設定。

下載 GoogleService-Info.plist 檔案,待會兒會用到。

如果不小心跳過了這個步驟,在 Firebase 專案設定裡面也可以找得到下載連結。

設定 GoogleService-Info.plist 的建置動作

將 GoogleService-Info.plist 檔案加入 xxx.iOS 專案之中,修改建置動作為 BundleResources

修改 Info.plist 設定

跟 Android App 一樣 iOS App 也是有自我介紹檔,這個自我介紹檔就是 Info.plist,要修改 Info.plist 我們可以用一般的文字編輯器打開它做修改,也可以在 Visual Studio 直接對 Info.plist 點擊左鍵兩下就會有修改的 GUI 出現。

套件組合識別碼

這個資訊就是我們剛剛輸入的 iOS 繫結 ID

遠端通知

我們從 Firebase 推播訊息到 iOS App 上算是一個 Remote Notification,App 在開發的時候就要事先設定並經由使用者授權,在「功能」->「背景模式」頁籤啟用背景模式及勾選遠端通知

模擬器不支援遠端通知,所以我們必須把 App 實際部署到實體機上。

產生 Apple 開發者憑證

這個開發者憑證主要是用在部署 App 到實體機或是上架到 App Store 用的,拿來確認這個 App 是真的由開發這個 App 的開發者所開發的。

要成為一名 Apple 開發者只有 Apple ID 是不夠的,還要繳 $99 鎂,除此之外也可以請別人邀請我們加入他的 Team,不然開發者後台就只是觀賞用的而已,不過建議還是繳 $99 鎂會方便很多。

我是選擇用加入別人 Team 的方式,在加入成功後,從 Xcode 的 Preferences 進入到 Accounts 頁籤,在這裡新增我們的 Apple ID。

接著我們就可以在 Team 裡面新增我們要用的憑證,因為我們沒有要上架到 App Store,所以選擇 iOS Development 類型的憑證就可以了。

完成後,我們就可以在 Apple 的開發者後台看到我們的 iOS Development 憑證。

建立 Authentication Key

需要 Authentication Key 是因為 Firebase 要推播到 iOS App 上還是需要 APNs(Apple Push Notification service)的幫忙,App 要使用 APNs 需要帶一個 Key,這個 Key 待會兒也需要上傳到 Firebase 去,我們在 Apple 開發者後台 Keys 這個區塊去新增 Key 並勾選 APNs。

產生之後把它下載下來,而且只能下載一次,所以要小心保存,遺失了就只能再新增一個。

產生 App ID

在 Apple 開發者後台去註冊一個 App ID,填入 App ID DescriptionBundle ID,勾選 Push Notifications,按下 Continue 確認後就註冊成功了。

上傳 APN 驗證金鑰到 Firebase

我們就把剛剛下載的 APNs Authentication Key 檔案上傳到 Firebase,上傳的介面在專案設定的 CLOUD MESSAGING 頁籤找得到,過程中還需要輸入金鑰 ID(Key ID)應用程式 ID 前置字串(Prefix),這兩個資訊在剛剛新增成功的 Authentication Key 及 App ID 裡面都找得到。

增加註冊遠端通知的程式碼

搞到現在一行 Code 都還沒寫,現在終於要來寫程式了,安裝 Xamarin.Firebase.iOS.CloudMessaging 套件然後按照著 Xamarin 官方的範例把程式碼加進去 AppDelegate.FinishedLaunching() 方法中,其中 AppDelegate 必須實作 IUNUserNotificationCenterDelegateIMessagingDelegate 這兩個 Interface,這個是為了 iOS 10+ 版本所調整的,至於差異在哪還沒空研究,剛剛搞這些設定已經讓我昏頭轉向了,有機會再進一步研究差異。

public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUNUserNotificationCenterDelegate, IMessagingDelegate
{
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        global::Xamarin.Forms.Forms.Init();

        Firebase.Core.App.Configure();

        this.LoadApplication(new App());

        // Register my app for remote notifications.
        if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
        {
            // iOS 10 or later
            var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;

            UNUserNotificationCenter.Current.RequestAuthorization(
                authOptions,
                (granted, error) => { Console.WriteLine(granted); });

            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.Current.Delegate = this;

            // For iOS 10 data message (sent via FCM)
            Messaging.SharedInstance.Delegate = this;
        }
        else
        {
            // iOS 9 or before
            var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;

            var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);

            UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
        }

        UIApplication.SharedApplication.RegisterForRemoteNotifications();

        return base.FinishedLaunching(app, options);
    }

    public void DidRefreshRegistrationToken(Messaging messaging, string fcmToken)
    {
        System.Diagnostics.Debug.WriteLine($"DidRefreshRegistrationToken FCM Token: {fcmToken}");
    }
}

建立 Provisioning Profile

Provisioning Profile 在做什麼,下面這段話已經說明得很清楚了。

一個 Provisioning Profile 檔包含了證書、App ID、設備的資訊。

試想一下,如果我們要打包或者在實體機上執行一個應用程式,我們首先需要證書來進行簽名,用來標識這個應用程式是合法的、安全的、完整的等等,然後需要指明它的 App ID,並且驗證 Bundle ID 是否與其一致,再次,如果是實體機偵錯,需要確認這台設備能否用來執行程式。而 Provisioning Profile 就把這些資訊全部打包在一起,方便我們在偵錯和部署程式打包時使用,這樣我們只要在不同的情況下選擇不同的 Profile 檔就可以了,而且這個 Provisioning Profile 檔會在打包時嵌入 .ipa 的包裡。

節錄自原文:https://read01.com/zP8kA.html

首先把實體機接上 Mac,然後參考這篇文章 Automatic Provisioning 將我們的實體機新增進 Apple 開發者後台的 Devices 清單裡面.。

接著新增 Provisioning Profile,需要填入的資訊不少,包含了 Provisioning TypeApp IDCertificatesDevicesProfile Name,新增成功之後把它下載下來。

把剛剛下載的 Provisioning Profile 檔案,藉由 Xcode 把它安裝進要部署 App 的目標實體機,從 Window -> Devices and Simulators 進去就會看到我們的實體機,選擇 Show Provisioning Profiles... 把 Provisioning Profile 檔案加進來。

測試發送

最後就把我們做的 iOS App 部署到實體機上,在 Android 那篇文章有提到過 Firebase 的後台有測試發送的服務,我們一樣可以透過測試發送的服務發給 iOS App。

參考資料

 < Source Code >

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學