Xamarin Android FCM 推播

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

張阿鬼 2017/09/15 17:30:15
1349







主題

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

文章簡介

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

作者:

張朝銘

版本/產出日期:

V1.0/2017.09.14




1. 前言

本文件用來提供Xamrin Android開發人員使用FCM實作推播通知

開發工具使用Visual Studio 2017/Xamarin Studio

本文件適用於Xamarin Android開發





2. 目的

使用FCM接收推播,取代原有的GCM推播



3. 本文

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

本篇文章會實做出一個接收FCM推播的APP,並藉由FCM的網頁介面發送推播。

建立Firebase專案

進入Firebaseconsole網頁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,該組tokenServer端要對單一裝置發送推播時的必須資訊。此外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新增特性ServiceIntentFilter複寫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,新增ServiceIntentFilter特性,並覆寫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());

}


private void SendNotification(RemoteMessage.Notification notification)

{

var notificationManager = NotificationManager.FromContext(this);

var builder = new Notification.Builder(Application.Context);

builder

.SetContentTitle(notification.Title)

.SetContentText(notification.Body)

.SetSmallIcon(Resource.Drawable.Icon)

.SetWhen(Java.Lang.JavaSystem.CurrentTimeMillis())

.SetDefaults(NotificationDefaults.All);

notificationManager.Notify(0, builder.Build());

}


推播類型之差異

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

顯示訊息:此種類型只有在APP於前景收到推播時會觸發OnMessageReceived()

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

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

4. 範例連結與參考來源

範例連結

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/



張阿鬼