[Xamarin.Android]使用FCM接收推播通知

  • 14184
  • 0

於Xamarin Android中如何使用FCM SDK接收推播

 

FCM全名為Firebase Cloud Messaging,是Google於2016年推出,用來取代原本的GCM,FCM簡化了不少開發步驟,也擁有一個UI介面可以直接發送推播等。雖然目前Google表示GCM因為還有許多開發者在使用,所以暫時不會停止支援GCM的服務。本篇文章會實做出一個接收FCM推播的APP,並藉由FCM的網頁介面發送推播。

建立Firebase專案
進入Firebase的console網頁https://console.firebase.google.com/u/0/,
並新增專案,輸入專案名稱、選擇地區後建立專案。

專案建立完成後,在專案的首頁選擇「將Firebase加入您的Android應用程式」。

輸入套件名稱與應用程式暱稱,點選註冊應用程式。

下載google-services.json檔案,後面的步驟會將該檔案加入至Xamarin.Android專案中。

新增Android專案,設定Package Name與權限

開啟新的Android專案後,進入專案屬性內將步驟3-1中所填寫的Android套件名稱,填入套件名稱欄位,並且勾選Internet權限。

安裝相關套件

為專案從Nuget中安裝以下套件

Ø   Xamarin.GooglePlayServices.Base

Ø   Xamarin.Firebase.Messaging

加入google-services.json檔案

將步驟3-1所下載的google-services.json檔案,加入至Android專案的根目錄下。

點選google-services.json,並在屬性視窗中調整建置動作為「GoogleServicesJson」。(若沒有看到GoogleServicesJson可選擇,請將VisualStudio關閉後重新開啟專案)

完成以上動作後,在建置專案時會自動將FCM相關所需的資訊寫入AndroidManifest.xml內(可從專案目錄\obj\Debug\android\AndroidManifest.xml觀察)

檢查Google Play Services

在Android裝置端中,第一層處理由FCM發送過來的推播依然是Google Play Service,因此裝置必須要有安裝該服務才收的到推播(通常可由有沒有裝Google Play判斷)。
首先在畫面上增加一個TextView顯示檢查的結果,並使用以下程式碼檢查是否有安裝Google Play Service。

Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <TextView
        android:text="Text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/lblState" />
</LinearLayout>

 

MainActivity.cs

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.Main);

            //檢查裝置上的googleservice服務
            var lblState = this.FindViewById<TextView>(Resource.Id.lblState);

            int checkResult = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
            if (checkResult != ConnectionResult.Success)
            {
                lblState.Text = 
                    GoogleApiAvailability.Instance.IsUserResolvableError(checkResult) ?
                    GoogleApiAvailability.Instance.GetErrorString(checkResult) :
                    "未偵測到Google Play Services ,無法使用";
                return;
            }
            lblState.Text = "Google Play Services 已偵測";
        }

完成後執行畫面如下

接收FCM Token

接著我們需要建立一個FirebaseInstanceIdService服務,接收由FCM 端發送過來的token,該組token是Server端要對單一裝置發送推播時的必須資訊。此外FCM也需要FirebaseInstanceIdService服務才能向裝置發送推播。FirebaseInstanceIdService會在APP處於背景狀態時,自動接收推播訊息並建立推播通知。

開啟專案中的AndroidManifest.xml並添加以下片段至application區塊內。

    <receiver
    android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver"
    android:exported="false" />
    <receiver
        android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND">
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="${applicationId}" />
      </intent-filter>
    </receiver>

   

建立Class並繼承FirebaseInstanceIdService,並在該Class新增特性Service、IntentFilter。複寫OnTokenRefresh()方法,由該方法中取得FCM傳來的Token,在該方法中通常會將取得的Token向自己APP的Server端發送並儲存下來,以利Server端日後可對單一裝置進行推播訊息。

    [Service]
    [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
    public class FirebaseIIDService: FirebaseInstanceIdService
    {
        public override void OnTokenRefresh()
        {
            //由FCM取得Token,或Token有更新時
            var refreshedToken = FirebaseInstanceId.Instance.Token;

            //to do somethings...(ex:throw the token to server)
        }
    }

   

OnTokenRefresh()只有在第一次取得Token,與以下狀況觸發

  • APP安裝或移除
  • 使用者清除APP資料
  • APP刪除了Instance ID
  • 當Token的安全性遭到破壞時
  • 定期性更新(依照Google文檔,Token約6個月會更新一次)

在畫面上新增一按鈕,該按鈕按下後顯示Token資訊於畫面。

   <Button
        android:text="顯示token"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnToken" />
            this.FindViewById<Button>(Resource.Id.btnToken).Click += (sender, e) =>
            {
                //印出Token
                Console.WriteLine(FirebaseInstanceId.Instance.Token);
                lblState.Text = FirebaseInstanceId.Instance.Token;
            };
 

Token取得之畫面

背景推播訊息

回到Google FCM Console網頁,在網頁上點選Notifications,點選「傳送第一則訊息」

填入要傳送的訊息內容訊息文字,並在目標處選擇「單一裝置」,將前步驟在裝置端取得的Token填入後按下傳送訊息(傳送前請確認APP已收到背景)。

進階選項處可設定是否有通知音效,更改推播訊息Title等。

發送後即會在裝置端接收到推播訊息。

(APP如在前景時收到推播則需要自行處理,這部分變得有點像iOS的模式)

可在專案中的AndroidManifest.xml設定收到推播時的icon圖示。將以下XML加入到application區段內。

    <meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/Icon" />

 

使用主題方式發送推播

在FCM的介面上,除了使用Token對單一介面做推播發送外,也可以使用指定主題的方式發送給有訂閱該主題的裝置。

在APP端新增一個按鈕進行主題的訂閱。

    <Button
        android:text="訂閱主題"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnSubscribe" />
            this.FindViewById<Button>(Resource.Id.btnSubscribe).Click += (sender, e) =>
            {
                //訂閱主題為test的推播
                FirebaseMessaging.Instance.SubscribeToTopic("test");
            };
 

在FCM的網頁介面則換成使用主題的方式發送,並輸入主題後發送。

處理前景推播

當APP在前景時收到推播,需要實做FirebaseMessagingService來處理收到的推播資料。建立一class並繼承FirebaseMessagingService,新增Service、IntentFilter特性,並覆寫OnMessageReceived()方法。
 

    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class FirebaseMessagingServiceTest : FirebaseMessagingService
    {
        public override void OnMessageReceived(RemoteMessage message)
        {

        }
    }

方法中傳入的message參數可取得由伺服器端發來的推播資訊。在此建立一個推播訊息

        public override void OnMessageReceived(RemoteMessage message)
        {
            //取得推播訊息
            this.SendNotification(message.GetNotification());
        }
        public override void OnMessageReceived(RemoteMessage message)
        {
            //取得推播訊息
            this.SendNotification(message.GetNotification());
        }

 

推播類型之差異

FCM的推播訊息分成兩種類型

  • 顯示訊息:此種類型只有在APP於前景收到推播時會觸發OnMessageReceived()
  • 資料訊息:此種類型在前景/背景/程序由Task移除狀態收到推播時,皆會觸發OnMessageReceived()。

由FCM網頁介面端發出的訊息都是屬於顯示訊息的類型,若要發送資料類型的推播訊息,則需呼叫FCM的API自行Post資料。

範例連結https://bitbucket.org/xamarinfroms/fcm.android/src

Xamarin官方網站

https://developer.xamarin.com/guides/android/application_fundamentals/notifications/firebase-cloud-messaging/

https://developer.xamarin.com/guides/android/application_fundamentals/notifications/remote-notifications-with-fcm/