共用方式為


Xamarin.Android 中的廣播接收器

本節討論如何使用廣播接收者。

廣播接收者概觀

廣播接收者是 Android 元件,可讓應用程式回應由 Android 作業系統或應用程式廣播的訊息(AndroidIntent)。 廣播會遵循 發佈-訂閱 模型 – 事件會導致對事件感興趣的元件發佈和接收廣播。

Android 會識別兩種類型的廣播:

  • 明確廣播 – 這些類型的廣播是以特定應用程式為目標。 明確廣播最常見的用法是啟動活動。 當應用程式需要撥打電話號碼時,明確廣播的範例;它會分派以Android上 電話 應用程式為目標的意圖,並傳遞要撥打的電話號碼。 Android 接著會將意圖路由傳送至 電話 應用程式。
  • 隱含廣播 – 這些廣播會分派到裝置上的所有應用程式。 隱含廣播的範例是 ACTION_POWER_CONNECTED 意圖。 每次 Android 偵測到裝置上的電池充電時,都會發布此意圖。 Android 會將此意圖路由傳送至已註冊此事件的所有應用程式。

廣播接收器是型別的 BroadcastReceiver 子類別,而且必須覆寫 OnReceive 方法。 Android 會在主線程上執行 OnReceive ,因此這個方法應該設計成快速執行。 在中 OnReceive 繁衍線程時,應該小心,因為Android可能會在方法完成時終止進程。 如果廣播接收者必須執行長時間執行的工作,建議使用 JobSchedulerFirebase 作業發送器來排程作業。 排程工作與作業將會在個別指南中討論。

意圖篩選可用來註冊廣播接收者,讓Android可以正確路由傳送訊息。 意圖篩選可以在運行時間指定(這有時稱為 內容註冊接收者動態註冊),也可以在Android指令清單中靜態定義( 指令清單註冊接收者)。 Xamarin.Android 提供 C# 屬性, IntentFilterAttribute以靜態方式註冊意圖篩選(本指南稍後將更詳細地討論)。 從 Android 8.0 開始,應用程式不可能以靜態方式註冊隱含廣播。

指令清單註冊接收者與內容註冊接收者之間的主要差異在於,內容註冊的接收者只會在應用程式執行時回應廣播,而指令清單註冊的接收者可以響應廣播,即使應用程式可能未執行也一樣。

有兩組 API 可用來管理廣播接收者和傳送廣播:

  1. Context – 類別 Android.Content.Context 可用來註冊廣播接收者,以回應全系統事件。 Context也用來發佈全系統廣播。
  2. LocalBroadcastManager– 這是可透過 Xamarin 支援連結庫 v4 NuGet 套件取得的 API。 這個類別可用來將廣播和廣播接收者隔離在使用它們的應用程式內容中。 這個類別對於防止其他應用程式回應僅限應用程式的廣播或將訊息傳送給私人接收者很有用。

廣播接收者可能不會顯示對話方塊,而且強烈建議您不要從廣播接收器內啟動活動。 如果廣播接收者必須通知使用者,則應該發佈通知。

無法從廣播接收器內系結或啟動服務。

本指南將說明如何建立廣播接收者,以及如何註冊它,以便接收廣播。

建立廣播接收者

若要在 Xamarin.Android 中建立廣播接收器,應用程式應該將 類別子類別 BroadcastReceiver 化、使用 BroadcastReceiverAttribute裝飾它,並覆寫 OnReceive 方法:

[BroadcastReceiver(Enabled = true, Exported = false)]
public class SampleReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Do stuff here.

        String value = intent.GetStringExtra("key");
    }
}

當 Xamarin.Android 編譯 類別時,它也會使用必要的元數據來更新 AndroidManifest 以註冊接收者。 如果是靜態註冊的廣播接收器, Enabled 則正確必須設定為 true,否則Android將無法建立接收者的實例。

屬性 Exported 控制廣播接收者是否可以從應用程式外部接收訊息。 如果未明確設定 屬性,則屬性的預設值是由 Android 根據是否有任何與廣播接收器相關聯的意圖篩選來決定。 如果廣播接收者至少有一個意圖篩選條件,則 Android 會假設 Exported 屬性為 true。 如果沒有與廣播接收者相關聯的意圖篩選,則 Android 會假設值為 false

方法 OnReceive 會接收已分派至廣播接收器之 的參考 Intent 。 這可讓意圖的傳送者將值傳遞至廣播接收者。

以靜態方式向意圖篩選註冊廣播接收者

BroadcastReceiver使用 裝飾 IntentFilterAttribute時,Xamarin.Android 會在編譯時期將必要的<intent-filter>元素新增至 Android 指令清單。 下列代碼段是廣播接收器的範例,會在裝置完成開機時執行(如果使用者授與適當的 Android 許可權):

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class MyBootReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Work that should be done when the device boots.     
    }
}

注意

在 Android 8.0(API 26 和更新版本)中, Google 會限制 應用程式在使用者未直接與應用程式互動時可以執行的動作。 這些限制會影響背景服務和隱含廣播接收者,例如 Android.Content.Intent.ActionBootCompleted。 由於這些限制,您可能會在較新版本的 Android 上註冊 Boot Completed 廣播接收器時發生困難。 如果是這種情況,請注意,這些限制不適用於前景服務,可從您的廣播接收器呼叫。

您也可以建立意圖篩選條件,以回應自定義意圖。 請考慮下列範例:

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "com.xamarin.example.TEST" })]
public class MySampleBroadcastReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Do stuff here
    }
}

以 Android 8.0 (API 層級 26) 或更新版本為目標的應用程式可能不會以靜態方式註冊隱含廣播。 應用程式仍可能以靜態方式註冊明確廣播。 有一小份隱含廣播清單,可免除這項限制。 這些例外狀況會在 Android檔中的隱含廣播例外 狀況指南中說明。 對隱含廣播感興趣的應用程式必須使用 方法以動態方式 RegisterReceiver 執行此動作。 接下來會說明這一點。

內容註冊廣播接收者

接收者的內容註冊(也稱為動態註冊)是藉由叫 RegisterReceiver 用 方法來執行,而且廣播接收者必須使用方法的呼叫 UnregisterReceiver 取消註冊。 若要防止資源流失,請務必在不再與內容(活動或服務)相關時取消註冊接收者。 例如,服務可能會廣播意圖來通知活動,讓活動能夠向用戶顯示更新。 當活動啟動時,它會註冊這些意圖。 當活動移至背景且使用者不再顯示時,它應該會取消註冊接收者,因為顯示更新的 UI 已不再顯示。 下列代碼段是如何在活動內容中註冊和取消註冊廣播接收器的範例:

[Activity(Label = "MainActivity", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity: Activity
{
    MySampleBroadcastReceiver receiver;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        receiver = new MySampleBroadcastReceiver();

        // Code omitted for clarity
    }

    protected override void OnResume()
    {
        base.OnResume();
        RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
        // Code omitted for clarity
    }

    protected override void OnPause()
    {
        UnregisterReceiver(receiver);
        // Code omitted for clarity
        base.OnPause();
    }
}

在上一個範例中,當活動進入前景時,它會註冊廣播接收器,以使用 OnResume 生命週期方法接聽自定義意圖。 當活動進入背景時, OnPause() 方法會取消註冊接收者。

發佈廣播

廣播可能會發佈至裝置上安裝的所有應用程式,以 建立 Intent 物件,並使用 或 SendOrderedBroadcast 方法分派它SendBroadcast

  1. Context.SendBroadcast 方法 – 這個方法有數個實作。 這些方法會將意圖廣播到整個系統。 將依不確定順序接收意圖的廣播接收者。 這提供很大的彈性,但表示其他應用程式可以註冊和接收意圖。 這可能會造成潛在的安全性風險。 應用程式可能需要實作新增安全性,以防止未經授權的存取。 其中一個可能的解決方案是使用 LocalBroadcastManager ,其只會在應用程式的私人空間內分派訊息。 此代碼段是如何使用其中一種方法分派意圖的 SendBroadcast 其中一個範例:

    Intent message = new Intent("com.xamarin.example.TEST");
    // If desired, pass some values to the broadcast receiver.
    message.PutExtra("key", "value");
    SendBroadcast(message);
    

    此代碼段是使用 Intent.SetAction 方法來識別動作的另一個傳送廣播範例:

    Intent intent = new Intent();
    intent.SetAction("com.xamarin.example.TEST");
    intent.PutExtra("key", "value");
    SendBroadcast(intent);
    
  2. Context.SendOrderedBroadcast – 這個方法非常類似 Context.SendBroadcast,其差異在於意圖會以接收者註冊的順序,一次發佈一個意圖給接收者。

LocalBroadcastManager

Xamarin 支援連結庫 v4 提供稱為 LocalBroadcastManager的協助程序類別。 LocalBroadcastManager適用於不想從裝置上其他應用程式傳送或接收廣播的應用程式。 LocalBroadcastManager只會在應用程式內容中發佈訊息,而且只會發佈至向 LocalBroadcastManager註冊的廣播接收者。 此代碼段是向 註冊廣播接收器 LocalBroadcastManager的範例:

Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this). RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));

裝置上的其他應用程式無法接收與一起 LocalBroadcastManager發佈的訊息。 此代碼段示範如何使用 來分派意圖 LocalBroadcastManager

Intent message = new Intent("com.xamarin.example.TEST");
// If desired, pass some values to the broadcast receiver.
message.PutExtra("key", "value");
Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this).SendBroadcast(message);