於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官方網站